1 /*
2
3 dsh-piccolo-tilemap Piccolo2D tile map nodes and supporting classes.
4 Copyright (c) 2006-2011 held jointly by the individual authors.
5
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 3 of the License, or (at
9 your option) any later version.
10
11 This library is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this library; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19
20 > http://www.fsf.org/licensing/licenses/lgpl.html
21 > http://www.opensource.org/licenses/lgpl-license.php
22
23 */
24 package org.dishevelled.piccolo.tilemap.io.impl;
25
26 import java.awt.Image;
27 import java.awt.image.BufferedImage;
28
29 import java.io.BufferedReader;
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34
35 import java.net.URL;
36
37 import java.util.ArrayList;
38 import java.util.List;
39
40 import org.dishevelled.piccolo.sprite.Animations;
41 import org.dishevelled.piccolo.sprite.Sprite;
42
43 import org.dishevelled.piccolo.tilemap.AbstractTileMap;
44 import org.dishevelled.piccolo.tilemap.SparseTileMap;
45
46 /**
47 * Flixel tile set + CSV file format tile map reader.
48 *
49 * @author Michael Heuer
50 * @version $Revision$ $Date$
51 */
52 public class FlixelTileMapReader
53 extends AbstractTileMapReader
54 {
55 /** Tile width in pixels. */
56 private final int tileWidth;
57
58 /** Tile height in pixels. */
59 private final int tileHeight;
60
61 /** List of tile images. */
62 private final List<Image> tiles;
63
64
65 /**
66 * Create a new flixel tile map reader with the specified tile set image.
67 *
68 * @param tileSet tile set image, must not be null
69 * @param tileWidth tile width in pixels
70 */
71 public FlixelTileMapReader(final BufferedImage tileSet, final int tileWidth)
72 {
73 this.tileWidth = tileWidth;
74 this.tileHeight = tileSet.getHeight();
75 tiles = Animations.createFrameList(tileSet, 0, 0, tileWidth, tileSet.getHeight(), tileSet.getWidth() / tileWidth);
76 }
77
78 /**
79 * Create a new flixel tile map reader with the specified tile set image input stream.
80 *
81 * @param tileSet tile set image input stream, must not be null
82 * @param tileWidth tile width in pixels
83 * @param tileHeight tile height in pixels
84 * @param frames number of frames
85 */
86 public FlixelTileMapReader(final InputStream tileSet, final int tileWidth, final int tileHeight, final int frames)
87 {
88 this.tileWidth = tileWidth;
89 this.tileHeight = tileHeight;
90 try
91 {
92 tiles = Animations.createFrameList(tileSet, 0, 0, tileWidth, tileHeight, frames);
93 }
94 catch (IOException e)
95 {
96 throw new RuntimeException("could not read from " + tileSet);
97 }
98 }
99
100 /**
101 * Create a new flixel tile map reader with the specified tile set image file.
102 *
103 * @param tileSet tile set image file, must not be null
104 * @param tileWidth tile width in pixels
105 * @param tileHeight tile height in pixels
106 * @param frames number of frames
107 */
108 public FlixelTileMapReader(final File tileSet, final int tileWidth, final int tileHeight, final int frames)
109 {
110 this.tileWidth = tileWidth;
111 this.tileHeight = tileHeight;
112 try
113 {
114 tiles = Animations.createFrameList(tileSet, 0, 0, tileWidth, tileHeight, frames);
115 }
116 catch (IOException e)
117 {
118 throw new RuntimeException("could not read from " + tileSet);
119 }
120 }
121
122 /**
123 * Create a new flixel tile map reader with the specified tile set image URL.
124 *
125 * @param tileSet tile set image URL, must not be null
126 * @param tileWidth tile width in pixels
127 * @param tileHeight tile height in pixels
128 * @param frames number of frames
129 */
130 public FlixelTileMapReader(final URL tileSet, final int tileWidth, final int tileHeight, final int frames)
131 {
132 this.tileWidth = tileWidth;
133 this.tileHeight = tileHeight;
134 try
135 {
136 tiles = Animations.createFrameList(tileSet, 0, 0, tileWidth, tileHeight, frames);
137 }
138 catch (IOException e)
139 {
140 throw new RuntimeException("could not read from " + tileSet);
141 }
142 }
143
144
145 /** {@inheritDoc} */
146 public AbstractTileMap read(final InputStream inputStream) throws IOException
147 {
148 if (inputStream == null)
149 {
150 throw new IllegalArgumentException ("inputStream must not be null");
151 }
152
153 // create separate sprites for each tile map
154 List<Sprite> tileSprites = new ArrayList<Sprite>(tiles.size());
155 for (Image tile : tiles)
156 {
157 // create new single frame animation for each sprite
158 tileSprites.add(new Sprite(Animations.createAnimation(tile)));
159 }
160 // this means that each copy of a sprite in the same tile map
161 // will be in sync
162 // but those in different tile maps will not necessarily be in sync
163 // ...though not sure how to specify multiple-frame sprites in this format
164
165 int rows = 0;
166 BufferedReader reader = null;
167 // too bad about this...
168 List<List<Sprite>> tmp = new ArrayList<List<Sprite>>();
169 try
170 {
171 reader = new BufferedReader(new InputStreamReader(inputStream));
172 while (reader.ready())
173 {
174 String line = reader.readLine();
175 List<Sprite> row = new ArrayList<Sprite>();
176 for (String value : line.split(","))
177 {
178 int index = Integer.valueOf(value);
179 if (index >= 0 && index < tileSprites.size())
180 {
181 row.add(tileSprites.get(index));
182 }
183 else
184 {
185 row.add(null);
186 }
187 }
188 tmp.add(row);
189 rows++;
190 }
191 }
192 catch (NumberFormatException e)
193 {
194 throw new IOException("caught NumberFormatException at line number " + rows
195 + "\n" + e.getMessage());
196 // jdk 1.6+
197 //throw new IOException("caught NumberFormatException at line number " + lineNumber, e);
198 }
199
200 SparseTileMap tileMap = new SparseTileMap(tmp.get(0).size(), tmp.size(), tileWidth, tileHeight);
201 for (int row = 0; row < tileHeight; row++)
202 {
203 for (int column = 0; column < tileWidth; column++)
204 {
205 Sprite sprite = tmp.get(row).get(column);
206 if (sprite != null)
207 {
208 tileMap.setTileRowColumn(row, column, sprite);
209 }
210 }
211 }
212 return tileMap;
213 }
214 }