root/trunk/TiledMap.java

Revision 149, 6.5 kB (checked in by kkhanna2, 6 months ago)

--

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1
2  //* TiledMap.java
3  //*loaded on demand.
4 // */
5  //* This is a map that is implemented as a grid of MapTiles, l
6
7 import java.awt.*;
8 import java.awt.geom.*;
9 import java.awt.image.*;
10 import java.io.*;
11 import java.net.*;
12
13 public class TiledMap extends BackgroundMap implements Serializable {
14         static final long serialVersionUID = 3890326970229567605L;
15
16
17         /**
18          * Creates a map which has a grid of rows x cols which covers an area
19          * of the world specified by realRectangle (in real coordinates).
20          */
21
22         public TiledMap(int rows, int columns, int rowHeight, int columnWidth, AffineTransform imageToReal) {
23                 this.rows = rows;
24                 this.columns = columns;
25                 this.rowHeight = rowHeight;
26                 this.columnWidth = columnWidth;
27
28                 setImageToReal(imageToReal);
29
30                 images = new Image[rows][columns];
31         }
32
33         public void setImageToReal(AffineTransform imageToReal) {
34                 this.imageToReal = imageToReal;
35                 try {
36                         realToImage = imageToReal.createInverse();
37                 } catch(NoninvertibleTransformException e) {
38                         throw new IllegalArgumentException("Couldn't invert the transform");
39                 }
40         }
41
42         public AffineTransform getImageToReal() { return imageToReal; }
43         public AffineTransform getRealToImage() { return realToImage; }
44
45         public Rectangle2D getRealBoundingRectangle() {
46                 return imageToReal
47                         .createTransformedShape(new Rectangle(0, 0, columns * columnWidth, rows * rowHeight))
48                         .getBounds2D();
49         };
50
51         /**
52          * Paints the map onto the given Graphics2D object, using realToScreen
53          * to transform the real coordinates the map knows about to screen
54          * coordinates it uses to draw on the Graphics2D.
55          */
56         public void paint(Graphics2D g, AffineTransform realToScreen, ImageObserver observer) {
57                 // determine the clipping region in real coordinates
58
59                 // figure out what it is in screen coordinates
60                 Rectangle2D screenClip = g.getClipBounds();
61                 if(screenClip == null) {
62 System.out.println("no clipping region");
63                         screenClip = new Rectangle2D.Double(
64                                 Double.NEGATIVE_INFINITY,
65                                 Double.NEGATIVE_INFINITY,
66                                 Double.POSITIVE_INFINITY,
67                                 Double.POSITIVE_INFINITY
68                         );
69                 }
70
71                 // get the transform
72                 AffineTransform screenToReal;
73                 try {
74                         screenToReal = realToScreen.createInverse();
75                 } catch(NoninvertibleTransformException e) {
76                         throw new IllegalArgumentException("Couldn't invert the transform");
77                 }
78
79                 // use transforms to figure out the clipping region in image coordinates
80                 Shape imageClip = realToImage.createTransformedShape(screenToReal.createTransformedShape(screenClip));
81
82                 // we use this to test for intersection
83                 Rectangle imageRectangle = new Rectangle(0, 0, columnWidth, rowHeight);
84
85                 // for all of our objects...
86                 for(int row = 0; row < rows; row++) {
87                         for(int column = 0; column < columns; column++) {
88                                 // skip if it isn't visible
89                                 imageRectangle.x = column * columnWidth;
90                                 imageRectangle.y = row * rowHeight;
91                                 if(!imageClip.intersects(imageRectangle)) continue;
92
93
94                                 // This is the place to implement more aggressive preloading
95                                 Image image = images[row][column];
96                                 if(image == null) {
97                                         image = getImage(row, column);
98                                         images[row][column] = image;
99                                 }
100
101                                 // tile (translate)-> image (imageToReal)-> real (realToScreen)-> screen
102                                 AffineTransform tileToScreen = new AffineTransform(realToScreen);
103                                 tileToScreen.concatenate(imageToReal);
104                                 tileToScreen.translate(imageRectangle.x, imageRectangle.y);
105
106                                 // ok, draw it.
107                                 g.drawImage(image, tileToScreen, observer);
108
109                         }
110                 }
111         }
112
113         private Image getImage(int row, int column) {
114 System.out.println("loading " + getUrl(row, column));
115                 return Toolkit.getDefaultToolkit().getImage(getUrl(row, column));
116         }
117
118         /**
119          * This returns the filename (no path components) for an image file at
120          * the given row and column in the grid.  It will be concatenated with
121          * the base and tree URIs.  It can be overridden for flexibility, though
122          * it may be easier in the long run not to.  The rows and columns start
123          * at 0, like arrays do.
124          *
125          * Note that it cannot be declared as static, because then even if
126          * subclasses override it, the subclass's version won't be run because
127          * the call will be resolved at compile time to this implementation.
128          */
129
130         public String getFilename(int row, int column) {
131                 return new String("row" + row + "column" + column + "." + extension);
132         }
133
134         public URL getUrl(int row, int column) {
135                 try {
136                         if(rootUri == null) rootUri = (new File(".")).toURI();
137                         if(treeUri == null) treeUri = new URI("");
138                         return rootUri.resolve(treeUri).resolve(new URI(getFilename(row, column))).toURL();
139                 } catch(Exception e) {
140                         throw new RuntimeException(e);
141                 }
142         }
143
144         public URI getRootUri() { return rootUri; }
145         public void setRootUri(String rootUri) {
146                 if(rootUri == null || rootUri.equals("")) {
147                         this.rootUri = null;
148                         return;
149                 }
150                 try {
151                         this.rootUri = new URI(rootUri);
152                 } catch(URISyntaxException e) {
153                         throw new IllegalArgumentException("malformed URI " + rootUri);
154                 }
155         }
156
157         public URI getTreeUri() { return treeUri; }
158         public void setTreeUri(String treeUri) {
159                 try {
160                         this.treeUri = new URI(treeUri);
161                 } catch(URISyntaxException e) {
162                         throw new IllegalArgumentException("malformed URI " + treeUri);
163                 }
164         }
165
166         public String getExtension() { return extension; }
167         public void setExtension(String extension) {
168                 this.extension = extension;
169         }
170
171         private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
172                 in.defaultReadObject();
173                 images = new Image[rows][columns];
174         }
175
176         // in pixels per meter
177         public double getPixelForPixelScale() {
178                 Rectangle2D boundingRect = getRealBoundingRectangle();
179                 double xScale = columns * columnWidth / boundingRect.getWidth();
180                 double yScale = rows * rowHeight / boundingRect.getHeight();
181                 return (xScale + yScale) / 2.0;
182         }
183
184         /**
185          * Where we get our pictures from.  This can be blank for the filesystem,
186          * or http://example.com/pathways/, for example.  Essentially the
187          * document root.
188          */
189         private transient URI rootUri;
190         /**
191          * The location in the tree our pictures come from.  For example,
192          * images/uiucmap/.  This is so that a map knows were to get its
193          * pictures, but we can move the directory tree between servers without
194          * changing code.
195          */
196         private URI treeUri;
197         /**
198          * The extension for the image files
199          */
200         private String extension;
201
202         // these must be kept inverse of each other
203         private AffineTransform imageToReal;
204         private AffineTransform realToImage;
205
206         /// how many rows and columns we have
207         private int rows, columns;
208         /// how big the rows and columns are
209         private int rowHeight, columnWidth;
210         /// our images, in [row][column]
211         private transient Image[][] images;
212 }
Note: See TracBrowser for help on using the browser.