View Javadoc

1   /*
2   
3       dsh-piccolo-tilemap  Piccolo2D tile map nodes and supporting classes.
4       Copyright (c) 2006-2013 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     @Override
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, e);
195         }
196 
197         SparseTileMap tileMap = new SparseTileMap(tmp.get(0).size(), tmp.size(), tileWidth, tileHeight);
198         for (int row = 0; row < tileHeight; row++)
199         {
200             for (int column = 0; column < tileWidth; column++)
201             {
202                 Sprite sprite = tmp.get(row).get(column);
203                 if (sprite != null)
204                 {
205                     tileMap.setTileRowColumn(row, column, sprite);
206                 }
207             }
208         }
209         return tileMap;
210    }
211 }