/**
*
* Copyright 2008 - 2011
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email javachenpeng@yahoo.com
* @version 0.1.0
*/
package loon.action.map.tmx;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import loon.LSystem;
import loon.LTouch;
import loon.Touch;
import loon.core.LRelease;
import loon.core.geom.RectBox;
import loon.core.graphics.opengl.GLEx;
import loon.core.graphics.opengl.LTexture;
import loon.core.resource.Resources;
import loon.utils.xml.XMLDocument;
import loon.utils.xml.XMLElement;
import loon.utils.xml.XMLParser;
public class TMXTiledMap implements LRelease {
protected int width;
protected int height;
protected int tileWidth;
protected int tileHeight;
private RectBox screenRect;
protected String tilesLocation;
protected TMXProperty props;
protected ArrayList<TMXTileSet> tileSets = new ArrayList<TMXTileSet>();
protected ArrayList<TMXLayer> layers = new ArrayList<TMXLayer>();
protected ArrayList<TMXTileGroup> objectGroups = new ArrayList<TMXTileGroup>();
private boolean loadTileSets = true;
private int defWidth, defHeight;
public TMXTiledMap(String fileName) throws RuntimeException {
this(fileName, true);
}
public TMXTiledMap(String fileName, boolean loadTileSets)
throws RuntimeException {
this.loadTileSets = loadTileSets;
fileName = fileName.replace('\\', '/');
String res = null;
if (fileName.indexOf("/") != -1) {
res = fileName.substring(0, fileName.lastIndexOf("/"));
} else {
res = fileName;
}
try {
this.load(Resources.openResource(fileName), res);
} catch (Exception e) {
e.printStackTrace();
}
}
public TMXTiledMap(String fileName, String tileSetsLocation)
throws RuntimeException {
try {
load(Resources.openResource(fileName), tileSetsLocation);
} catch (IOException e) {
e.printStackTrace();
}
}
public TMXTiledMap(InputStream in) throws RuntimeException {
load(in, "");
}
public TMXTiledMap(InputStream in, String tileSetsLocation)
throws RuntimeException {
load(in, tileSetsLocation);
}
public String getTilesLocation() {
return tilesLocation;
}
public int getLayerIndex(String name) {
for (int i = 0; i < layers.size(); i++) {
TMXLayer layer = layers.get(i);
if (layer.name.equals(name)) {
return i;
}
}
return -1;
}
public LTexture getTileImage(int x, int y, int layerIndex) {
TMXLayer layer = layers.get(layerIndex);
int tileSetIndex = layer.data[x][y][0];
if ((tileSetIndex >= 0) && (tileSetIndex < tileSets.size())) {
TMXTileSet tileSet = tileSets.get(tileSetIndex);
int sheetX = tileSet.getTileX(layer.data[x][y][1]);
int sheetY = tileSet.getTileY(layer.data[x][y][1]);
return tileSet.tiles.getSubImage(sheetX, sheetY);
}
return null;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getTileHeight() {
return tileHeight;
}
public int getTileWidth() {
return tileWidth;
}
public TMXLayer getLayer(int id) {
return layers.get(id);
}
public int getTileId(int x, int y, int layerIndex) {
TMXLayer layer = layers.get(layerIndex);
return layer.getTileID(x, y);
}
public void setTileId(int x, int y, int layerIndex, int tileid) {
TMXLayer layer = layers.get(layerIndex);
layer.setTileID(x, y, tileid);
}
public String getMapProperty(String propertyName, String def) {
if (props == null)
return def;
return props.getProperty(propertyName, def);
}
public String getLayerProperty(int layerIndex, String propertyName,
String def) {
TMXLayer layer = layers.get(layerIndex);
if (layer == null || layer.props == null)
return def;
return layer.props.getProperty(propertyName, def);
}
public String getTileProperty(int tileID, String propertyName, String def) {
if (tileID == 0) {
return def;
}
TMXTileSet set = findTileSet(tileID);
TMXProperty props = set.getProperties(tileID);
if (props == null) {
return def;
}
return props.getProperty(propertyName, def);
}
public void draw(GLEx g, LTouch e) {
int x = e.x() / tileWidth;
int y = e.y() / tileHeight;
draw(g, 0, 0, x, y, width - defWidth, height - defHeight, false);
}
public void draw(GLEx g) {
int x = Touch.x() / tileWidth;
int y = Touch.y() / tileHeight;
draw(g, 0, 0, x, y, width - defWidth, height - defHeight, false);
}
public void draw(GLEx g, int tx, int ty) {
draw(g, 0, 0, tx, ty);
}
public void draw(GLEx g, int x, int y, int tx, int ty) {
draw(g, x, y, tx, ty, defWidth, defHeight, false);
}
public void draw(GLEx g, int x, int y, int layer) {
draw(g, x, y, 0, 0, getWidth(), getHeight(), layer, false);
}
public void draw(GLEx g, int x, int y, int sx, int sy, int width, int height) {
draw(g, x, y, sx, sy, width, height, false);
}
public void draw(GLEx g, int x, int y, int sx, int sy, int width,
int height, int index, boolean lineByLine) {
TMXLayer layer = layers.get(index);
layer.draw(g, x, y, sx, sy, width, height, lineByLine, tileWidth,
tileHeight);
}
public void draw(GLEx g, int x, int y, int sx, int sy, int width,
int height, boolean lineByLine) {
for (int i = 0; i < layers.size(); i++) {
TMXLayer layer = layers.get(i);
layer.draw(g, x, y, sx, sy, width, height, lineByLine, tileWidth,
tileHeight);
}
}
public int getLayerCount() {
return layers.size();
}
private void load(InputStream in, String tileSetsLocation)
throws RuntimeException {
screenRect = LSystem.screenRect;
tilesLocation = tileSetsLocation;
try {
XMLDocument doc = XMLParser.parse(in);
XMLElement docElement = doc.getRoot();
String orient = docElement.getAttribute("orientation", "");
if (!"orthogonal".equals(orient)) {
throw new RuntimeException(
"Only orthogonal maps supported, found " + orient);
}
width = docElement.getIntAttribute("width", 0);
height = docElement.getIntAttribute("height", 0);
tileWidth = docElement.getIntAttribute("tilewidth", 0);
tileHeight = docElement.getIntAttribute("tileheight", 0);
XMLElement propsElement = docElement
.getChildrenByName("properties");
if (propsElement != null) {
props = new TMXProperty();
ArrayList<XMLElement> property = propsElement.list("property");
for (int i = 0; i < property.size(); i++) {
XMLElement propElement = property.get(i);
String name = propElement.getAttribute("name", null);
String value = propElement.getAttribute("value", null);
props.setProperty(name, value);
}
}
if (loadTileSets) {
TMXTileSet tileSet = null;
TMXTileSet lastSet = null;
ArrayList<XMLElement> setNodes = docElement.list("tileset");
for (int i = 0; i < setNodes.size(); i++) {
XMLElement current = setNodes.get(i);
tileSet = new TMXTileSet(this, current, true);
tileSet.index = i;
if (lastSet != null) {
lastSet.setLimit(tileSet.firstGID - 1);
}
lastSet = tileSet;
tileSets.add(tileSet);
}
}
ArrayList<XMLElement> layerNodes = docElement.list("layer");
for (int i = 0; i < layerNodes.size(); i++) {
XMLElement current = layerNodes.get(i);
TMXLayer layer = new TMXLayer(this, current);
layer.index = i;
layers.add(layer);
}
ArrayList<XMLElement> objectGroupNodes = docElement
.list("objectgroup");
for (int i = 0; i < objectGroupNodes.size(); i++) {
XMLElement current = objectGroupNodes.get(i);
TMXTileGroup objectGroup = new TMXTileGroup(current);
objectGroup.index = i;
objectGroups.add(objectGroup);
}
defWidth = (int) (screenRect.getWidth() / tileWidth);
defHeight = (int) (screenRect.getHeight() / tileHeight);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException("Failed to parse map", ex);
}
}
public int getScreenWidth() {
return defWidth;
}
public int getScreenHeight() {
return defHeight;
}
public int getTileSetCount() {
return tileSets.size();
}
public TMXTileSet getTileSet(int index) {
return tileSets.get(index);
}
public TMXTileSet getTileSetByGID(int gid) {
for (int i = 0; i < tileSets.size(); i++) {
TMXTileSet set = tileSets.get(i);
if (set.contains(gid)) {
return set;
}
}
return null;
}
public TMXTileSet findTileSet(int gid) {
for (int i = 0; i < tileSets.size(); i++) {
TMXTileSet set = tileSets.get(i);
if (set.contains(gid)) {
return set;
}
}
return null;
}
protected void draw(GLEx g, int x, int y, int sx, int sy, int width,
int height, int layer) {
}
public int getObjectGroupCount() {
return objectGroups.size();
}
public int getObjectCount(int groupID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
return grp.objects.size();
}
return -1;
}
public String getObjectName(int groupID, int objectID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
return object.name;
}
}
return null;
}
public String getObjectType(int groupID, int objectID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
return object.type;
}
}
return null;
}
public int getObjectX(int groupID, int objectID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
return object.x;
}
}
return -1;
}
public int getObjectY(int groupID, int objectID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
return object.y;
}
}
return -1;
}
public int getObjectWidth(int groupID, int objectID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
return object.width;
}
}
return -1;
}
public int getObjectHeight(int groupID, int objectID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
return object.height;
}
}
return -1;
}
public String getObjectImage(int groupID, int objectID) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
if (object == null) {
return null;
}
return object.image;
}
}
return null;
}
public String getObjectProperty(int groupID, int objectID,
String propertyName, String def) {
if (groupID >= 0 && groupID < objectGroups.size()) {
TMXTileGroup grp = objectGroups.get(groupID);
if (objectID >= 0 && objectID < grp.objects.size()) {
TMXTile object = grp.objects.get(objectID);
if (object == null) {
return def;
}
if (object.props == null) {
return def;
}
return object.props.getProperty(propertyName, def);
}
}
return def;
}
public void dispose() {
if (tileSets != null) {
for (TMXTileSet tmx : tileSets) {
if (tmx != null) {
tmx.dispose();
tmx = null;
}
}
}
}
}