--- /dev/null
+package com.badlogic.gdx.maps.tiled;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+import com.badlogic.gdx.assets.AssetDescriptor;
+import com.badlogic.gdx.assets.AssetLoaderParameters;
+import com.badlogic.gdx.assets.AssetManager;
+import com.badlogic.gdx.assets.loaders.FileHandleResolver;
+import com.badlogic.gdx.assets.loaders.SynchronousAssetLoader;
+import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.maps.ImageResolver;
+import com.badlogic.gdx.maps.MapProperties;
+import com.badlogic.gdx.maps.ImageResolver.AssetManagerImageResolver;
+import com.badlogic.gdx.maps.ImageResolver.DirectImageResolver;
+import com.badlogic.gdx.maps.tiled.tiles.AnimatedTiledMapTile;
+import com.badlogic.gdx.maps.tiled.tiles.StaticTiledMapTile;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.GdxRuntimeException;
+import com.badlogic.gdx.utils.ObjectMap;
+import com.badlogic.gdx.utils.XmlReader;
+import com.badlogic.gdx.utils.XmlReader.Element;
+
+public class TideMapLoader extends SynchronousAssetLoader<TiledMap, TideMapLoader.Parameters> {
+
+ public static class Parameters extends AssetLoaderParameters<TiledMap> {
+
+ }
+
+ private XmlReader xml = new XmlReader();
+ private Element root;
+
+ public TideMapLoader() {
+ super(new InternalFileHandleResolver());
+ }
+
+ public TideMapLoader (FileHandleResolver resolver) {
+ super(resolver);
+ }
+
+ public TiledMap load (String fileName) {
+ try {
+ FileHandle tideFile = resolve(fileName);
+ root = xml.parse(tideFile);
+ ObjectMap<String, Texture> textures = new ObjectMap<String, Texture>();
+ for(FileHandle textureFile: loadTileSheets(root, tideFile)) {
+ textures.put(textureFile.path(), new Texture(textureFile));
+ }
+ DirectImageResolver imageResolver = new DirectImageResolver(textures);
+ TiledMap map = loadMap(root, tideFile, imageResolver);
+ map.setOwnedTextures(textures.values().toArray());
+ return map;
+ } catch(IOException e) {
+ throw new GdxRuntimeException("Couldn't load tilemap '" + fileName + "'", e);
+ }
+
+ }
+
+ @Override
+ public TiledMap load (AssetManager assetManager, String fileName, Parameters parameter) {
+ FileHandle tideFile = resolve(fileName);
+ try {
+ return loadMap(root, tideFile, new AssetManagerImageResolver(assetManager));
+ } catch (Exception e) {
+ throw new GdxRuntimeException("Couldn't load tilemap '" + fileName + "'", e);
+ }
+ }
+
+ @Override
+ public Array<AssetDescriptor> getDependencies (String fileName, Parameters parameter) {
+ Array<AssetDescriptor> dependencies = new Array<AssetDescriptor>();
+ try {
+ FileHandle tmxFile = resolve(fileName);
+ root = xml.parse(tmxFile);
+ for(FileHandle image: loadTileSheets(root, tmxFile)) {
+ dependencies.add(new AssetDescriptor(image.path(), Texture.class));
+ }
+ return dependencies;
+ } catch (IOException e) {
+ throw new GdxRuntimeException("Couldn't load tilemap '" + fileName + "'", e);
+ }
+ }
+
+ /**
+ * Loads the map data, given the XML root element and an {@link ImageResolver} used
+ * to return the tileset Textures
+ * @param root the XML root element
+ * @param tmxFile the Filehandle of the tmx file
+ * @param imageResolver the {@link ImageResolver}
+ * @return the {@link TiledMap}
+ */
+ private TiledMap loadMap(Element root, FileHandle tmxFile, ImageResolver imageResolver) {
+ TiledMap map = new TiledMap();
+ Element properties = root.getChildByName("properties");
+ if (properties != null) {
+ loadProperties(map.getProperties(), properties);
+ }
+ Element tilesheets = root.getChildByName("TileSheets");
+ for (Element tilesheet : tilesheets.getChildrenByName("TileSheet")) {
+ loadTileSheet(map, tilesheet, tmxFile, imageResolver);
+ }
+ Element layers = root.getChildByName("Layers");
+ for (Element layer : layers.getChildrenByName("Layer")) {
+ loadLayer(map, layer);
+ }
+ return map;
+ }
+
+ /**
+ * Loads the tilesets
+ * @param root the root XML element
+ * @return a list of filenames for images containing tiles
+ * @throws IOException
+ */
+ private Array<FileHandle> loadTileSheets(Element root, FileHandle tideFile) throws IOException {
+ Array<FileHandle> images = new Array<FileHandle>();
+ Element tilesheets = root.getChildByName("TileSheets");
+ for (Element tileset : tilesheets.getChildrenByName("TileSheet")) {
+ Element imageSource = tileset.getChildByName("ImageSource");
+ FileHandle image = getRelativeFileHandle(tideFile, imageSource.getText());
+ images.add(image);
+ }
+ return images;
+ }
+
+ private void loadTileSheet(TiledMap map, Element element, FileHandle tideFile, ImageResolver imageResolver) {
+ if (element.getName().equals("TileSheet")) {
+ String id = element.getAttribute("Id");
+ String description = element.getChildByName("Description").getText();
+ String imageSource = element.getChildByName("ImageSource").getText();
+
+ Element alignment = element.getChildByName("Alignment");
+ String sheetSize = alignment.getAttribute("SheetSize");
+ String tileSize = alignment.getAttribute("TileSize");
+ String margin = alignment.getAttribute("Margin");
+ String spacing = alignment.getAttribute("Spacing");
+
+ String[] sheetSizeParts = sheetSize.split(" x ");
+ int sheetSizeX = Integer.parseInt(sheetSizeParts[0]);
+ int sheetSizeY = Integer.parseInt(sheetSizeParts[1]);
+
+ String[] tileSizeParts = tileSize.split(" x ");
+ int tileSizeX = Integer.parseInt(tileSizeParts[0]);
+ int tileSizeY = Integer.parseInt(tileSizeParts[1]);
+
+ String[] marginParts = margin.split(" x ");
+ int marginX = Integer.parseInt(marginParts[0]);
+ int marginY = Integer.parseInt(marginParts[1]);
+
+ String[] spacingParts = margin.split(" x ");
+ int spacingX = Integer.parseInt(spacingParts[0]);
+ int spacingY = Integer.parseInt(spacingParts[1]);
+
+ FileHandle image = getRelativeFileHandle(tideFile, imageSource);
+ Texture texture = imageResolver.getImage(image.path());
+
+ // TODO: Actually load the tilesheet
+ // Need to make global ids as Tide doesn't have global ids.
+ TiledMapTileSets tilesets = map.getTileSets();
+ int firstgid = 1;
+ for (TiledMapTileSet tileset : tilesets) {
+ firstgid += tileset.size();
+ }
+
+ TiledMapTileSet tileset = new TiledMapTileSet();
+ tileset.setName(id);
+ tileset.getProperties().put("firstgid", firstgid);
+ int gid = firstgid;
+
+ int stopWidth = texture.getWidth() - tileSizeX;
+ int stopHeight = texture.getHeight() - tileSizeY;
+
+ for (int y = marginY; y <= stopHeight; y += tileSizeY + spacingY) {
+ for (int x = marginX; x <= stopWidth; x += tileSizeX + spacingX) {
+ TiledMapTile tile = new StaticTiledMapTile(new TextureRegion(texture, x, y, tileSizeX, tileSizeY));
+ tileset.putTile(gid++, tile);
+ }
+ }
+
+ Element properties = element.getChildByName("Proeprties");
+ if (properties != null) {
+ loadProperties(tileset.getProperties(), properties);
+ }
+
+ tilesets.addTileSet(tileset);
+ }
+ }
+
+ private void loadLayer(TiledMap map, Element element) {
+ if (element.getName().equals("Layer")) {
+ String id = element.getAttribute("Id");
+ String visible = element.getAttribute("Visible");
+
+ Element dimensions = element.getChildByName("Dimensions");
+ String layerSize = dimensions.getAttribute("LayerSize");
+ String tileSize = dimensions.getAttribute("TileSize");
+
+ String[] layerSizeParts = layerSize.split(" x ");
+ int layerSizeX = Integer.parseInt(layerSizeParts[0]);
+ int layerSizeY = Integer.parseInt(layerSizeParts[1]);
+
+ String[] tileSizeParts = tileSize.split(" x ");
+ int tileSizeX = Integer.parseInt(tileSizeParts[0]);
+ int tileSizeY = Integer.parseInt(tileSizeParts[1]);
+
+ TiledMapTileLayer layer = new TiledMapTileLayer(layerSizeX, layerSizeY, tileSizeX, tileSizeY);
+ Element tileArray = element.getChildByName("TileArray");
+ Array<Element> rows = tileArray.getChildrenByName("Row");
+ TiledMapTileSets tilesets = map.getTileSets();
+ TiledMapTileSet currentTileSet = null;
+ int firstgid = 0;
+ int x, y;
+ for (int row = 0, rowCount = rows.size; row < rowCount; row++) {
+ Element currentRow = rows.get(row);
+ y = row;
+ x = 0;
+ for (int child = 0, childCount = currentRow.getChildCount(); child < childCount; child++) {
+ Element currentChild = currentRow.getChild(child);
+ String name = currentChild.getName();
+ if (name.equals("TileSheet")) {
+ currentTileSet = tilesets.getTileSet(currentChild.getAttribute("Ref"));
+ firstgid = currentTileSet.getProperties().getAsInteger("firstgid");
+ } else if (name.equals("Null")) {
+ x += currentChild.getIntAttribute("Count");
+ } else if (name.equals("Static")) {
+ layer.setCell(x, y, currentTileSet.getTile(firstgid + currentChild.getIntAttribute("Index")));
+ } else if (name.equals("Animated")) {
+ // Create an AnimatedTile
+ int interval = currentChild.getInt("Interval");
+ Element frames = currentChild.getChildByName("Frames");
+ Array<StaticTiledMapTile> frameTiles = new Array<StaticTiledMapTile>();
+ for (int frameChild = 0, frameChildCount = frames.getChildCount(); frameChild < frameChildCount; frameChild++) {
+ Element frame = frames.getChild(frameChild);
+ String frameName = frame.getName();
+ if (frameName.equals("TileSheet")) {
+ currentTileSet = tilesets.getTileSet(currentChild.getAttribute("Ref"));
+ firstgid = currentTileSet.getProperties().getAsInteger("firstgid");
+ } else if (frameName.equals("Static")) {
+ frameTiles.add((StaticTiledMapTile) currentTileSet.getTile(firstgid + frame.getIntAttribute("Index")));
+ }
+ }
+ layer.setCell(x, y, new AnimatedTiledMapTile(interval / 1000f, frameTiles)); //TODO: Reuse existing animated tiles
+ }
+ }
+ }
+ }
+ }
+
+ private void loadProperties(MapProperties properties, Element element) {
+ if (element.getName().equals("Properties")) {
+ for (Element property : element.getChildrenByName("Property")) {
+ String key = property.getAttribute("Key", null);
+ String type = property.getAttribute("Type", null);
+ String value = property.getText();
+
+ if (type.equals("Int32")) {
+
+ } else if (type.equals("String")) {
+
+ } else if (type.equals("Boolean")) {
+
+ } else {
+ properties.put(key, value);
+ }
+ }
+ }
+ }
+
+ private static FileHandle getRelativeFileHandle(FileHandle file, String path) {
+ StringTokenizer tokenizer = new StringTokenizer(path, "\\/");
+ FileHandle result = file.parent();
+ while (tokenizer.hasMoreElements()) {
+ String token = tokenizer.nextToken();
+ if (token.equals(".."))
+ result = result.parent();
+ else {
+ result = result.child(token);
+ }
+ }
+ return result;
+ }
+
+}
package com.badlogic.gdx.maps.tiled;
-import static com.badlogic.gdx.graphics.g2d.SpriteBatch.*;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.C1;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.C2;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.C3;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.C4;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.U1;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.U2;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.U3;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.U4;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.V1;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.V2;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.V3;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.V4;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.X1;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.X2;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.X3;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.X4;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.Y1;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.Y2;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.Y3;
+import static com.badlogic.gdx.graphics.g2d.SpriteBatch.Y4;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GL11;
+import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.SpriteCache;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
-import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.maps.MapLayer;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.math.Matrix4;
-import com.badlogic.gdx.math.Polygon;
import com.badlogic.gdx.math.Rectangle;
public interface TiledMapRenderer {
- public void setViewBounds(float x, float y, float width, float height);
-
- public void setProjectionMatrix(Matrix4 projection);
+ public void setView(Matrix4 projectionMatrix, float viewBoundsX, float viewBoundsY, float viewBoundsWidth, float viewBoundsHeight);
+ public void setView(OrthographicCamera camera);
public void begin();
public void end();
}
@Override
- public void setViewBounds (float x, float y, float width, float height) {
- viewBounds.set(x, y, width, height);
+ public void setView(Matrix4 projectionMatrix, float viewBoundsX, float viewBoundsY, float viewBoundsWidth, float viewBoundsHeight) {
+ spriteBatch.setProjectionMatrix(projectionMatrix);
+ viewBounds.set(viewBoundsX, viewBoundsY, viewBoundsWidth, viewBoundsHeight);
}
@Override
- public void setProjectionMatrix (Matrix4 projection) {
- spriteBatch.setProjectionMatrix(projection);
+ public void setView(OrthographicCamera camera) {
+ setView(camera.combined, camera.position.x - camera.viewportWidth / 2, camera.position.y - camera.viewportHeight / 2, camera.viewportWidth, camera.viewportHeight);
}
@Override
}
@Override
- public void setViewBounds (float x, float y, float width, float height) {
- viewBounds.set(x, y, width, height);
+ public void setView(Matrix4 projectionMatrix, float viewBoundsX, float viewBoundsY, float viewBoundsWidth, float viewBoundsHeight) {
+ spriteCache.setProjectionMatrix(projectionMatrix);
+ viewBounds.set(viewBoundsX, viewBoundsY, viewBoundsWidth, viewBoundsHeight);
}
@Override
- public void setProjectionMatrix (Matrix4 projection) {
- spriteCache.setProjectionMatrix(projection);
+ public void setView(OrthographicCamera camera) {
+ setView(camera.combined, camera.position.x - camera.viewportWidth / 2, camera.position.y - camera.viewportHeight / 2, camera.viewportWidth, camera.viewportHeight);
}
@Override
}
- public class OrthogonalTiledMapRenderer2 implements TiledMapRenderer {
+ public class OrthogonalTiledMapRenderer2 extends CacheTiledMapRenderer {
protected TiledMap map;
public boolean recache;
public OrthogonalTiledMapRenderer2(TiledMap map) {
- this.map = map;
- this.unitScale = 1;
- this.spriteCache = new SpriteCache(4000, true);
- this.viewBounds = new Rectangle();
+ super(map);
}
public OrthogonalTiledMapRenderer2(TiledMap map, float unitScale) {
- this.map = map;
- this.unitScale = unitScale;
- this.viewBounds = new Rectangle();
- this.spriteCache = new SpriteCache(4000, true);
- }
-
- @Override
- public void setViewBounds (float x, float y, float width, float height) {
- viewBounds.set(x, y, width, height);
- }
-
- @Override
- public void setProjectionMatrix (Matrix4 projection) {
- spriteCache.setProjectionMatrix(projection);
+ super(map, unitScale);
}
@Override
}
- @Override
- public void renderObject (MapObject object) {
- // TODO Auto-generated method stub
-
- }
-
boolean cached = false;
int count = 0;
@Override