From 6af1b95e8966e40e71a4cc4f8563174cb86e51bf Mon Sep 17 00:00:00 2001 From: "oskar.wiksten" Date: Mon, 10 Oct 2011 20:48:48 +0000 Subject: [PATCH] Slight performance improvement to TMX file reader. Added Android application description. Conversation correction to Buceth. Tweaked droplists that contains potions. git-svn-id: https://andors-trail.googlecode.com/svn/trunk@176 08aca716-68be-ccc6-4d58-36f5abd142ac --- AndorsTrail/AndroidManifest.xml | 1 + .../res/values/content_conversationlist.xml | 2 +- AndorsTrail/res/values/content_droplist.xml | 18 +- AndorsTrail/res/values/strings.xml | 1 + .../controller/MovementController.java | 4 +- ...MXMapReader.java => TMXMapFileParser.java} | 272 ++------------- .../model/map/TMXMapTranslator.java | 319 ++++++++++++++++++ .../AndorsTrail/resource/ResourceLoader.java | 4 +- 8 files changed, 360 insertions(+), 261 deletions(-) rename AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/{TMXMapReader.java => TMXMapFileParser.java} (50%) create mode 100644 AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java diff --git a/AndorsTrail/AndroidManifest.xml b/AndorsTrail/AndroidManifest.xml index 9e8ec09..a26ec43 100644 --- a/AndorsTrail/AndroidManifest.xml +++ b/AndorsTrail/AndroidManifest.xml @@ -24,6 +24,7 @@ android:name=".AndorsTrailApplication" android:label="@string/app_name" android:icon="@drawable/icon" + android:description="@string/app_description" > [id|items[itemID|quantity_Min|quantity_Max|chance|]|]; -{cavemonster|{{gold|4|12|70|}{gem2|1|1|25|}{hammer0|1|1|5|}{health_minor2|1|1|25|}}|}; +{cavemonster|{{gold|4|12|70|}{gem2|1|1|25|}{hammer0|1|1|5|}{health_minor|1|1|25|}}|}; {snake|{{gold|3|6|70|}{meat|1|1|30|}{gland|1|1|5|}}|}; {haunt|{{vial_empty1|1|1|25|}{gem1|1|1|25|}}|}; {cavecritter|{{gold|4|8|70|}{gem1|1|1|25|}{claws|1|1|30|}}|}; -{lich1|{{gold|5|15|70|}{gem2|1|1|25|}{health_minor2|1|1|25|}}|}; +{lich1|{{gold|5|15|70|}{gem2|1|1|25|}{health_minor|1|1|25|}}|}; {irogotu|{{neck_irogotu|1|1|100|}{ring_gandir|1|1|100|}{health|1|1|100|}}|}; {canineboss|{{gold|7|10|70|}{hair|1|1|30|}{gem1|1|1|25|}{meat|1|1|30|}{boots1|1|1|25|}}|}; {snakemaster|{{gold|9|9|70|}{dagger_venom|1|1|100|}{gem3|1|1|100|}{health|1|1|100|}}|}; @@ -35,7 +35,7 @@ [id|items[itemID|quantity_Min|quantity_Max|chance|]|]; {catacombrat|{{gold|1|5|70|}{gem1|1|1|25|}{vial_empty1|1|1|25|}}|}; {skeleton|{{gold|16|23|70|}{gem2|1|1|25|}{health|1|1|25|}{bone|1|1|30|}}|}; -{luthor|{{gold|1|5|70|}{gem1|1|1|100|}{key_luthor|1|1|100|}{health_major2|1|1|100|}}|}; +{luthor|{{gold|1|5|70|}{gem1|1|1|100|}{key_luthor|1|1|100|}{health_major|1|1|100|}}|}; {shop_thoronir|{{bonemeal_potion|10|10|100|}}|}; {larcal|{{gold|4|12|70|}{club1|1|1|100|}{calomyran_secrets|1|1|100|}{milk|1|1|100|}}|}; {catacombguard|{{gold|4|12|70|}{gem2|1|1|25|}{health|1|1|25|}{vial_empty2|1|1|25|}{gloves1|1|1|5|}}|}; @@ -143,7 +143,7 @@ {kazaul_1|{ {gold|3|19|70|} {gem4|1|1|10|} - {health_minor2|1|1|10|} + {health_minor|1|1|10|} {rock|1|1|5|} }|}; {kazaul_2|{ @@ -156,7 +156,7 @@ {restless_dead_1|{ {gold|20|29|70|} {gem3|1|1|10|} - {health_minor2|1|1|10|} + {health_minor|1|1|10|} {bone|1|1|10|} }|}; {restless_dead_2|{ @@ -191,13 +191,13 @@ {gold|1|30|70|} {bone|1|1|10|} {vial_empty1|1|1|25|} - {health_minor2|1|1|10|} + {health_minor|1|1|10|} }|}; {wyrm_2|{ {gold|1|40|70|} {bone|1|1|10|} {vial_empty1|1|1|25|} - {health_minor2|1|2|10|} + {health_minor|1|2|10|} }|}; {wyrm_3|{ {gold|1|60|70|} @@ -211,7 +211,7 @@ {bone|1|2|10|} {vial_empty1|1|1|25|} {pot_poison_weak|1|3|5|} - {health_minor2|1|2|10|} + {health_minor|1|2|10|} {elytharan_redeemer|1|1|1/10000|} }|}; {aulaeth|{ @@ -423,7 +423,7 @@ {ring_villain|1|1|100|} }|}; {shop_tharal|{ - {health_minor|10|10|100|} + {health_minor2|10|10|100|} {health|10|10|100|} {health_major2|10|10|100|} {necklace_shield_0|1|1|100|} diff --git a/AndorsTrail/res/values/strings.xml b/AndorsTrail/res/values/strings.xml index f1f2a51..1cdb08d 100644 --- a/AndorsTrail/res/values/strings.xml +++ b/AndorsTrail/res/values/strings.xml @@ -2,6 +2,7 @@ Andor\'s Trail + Quest-driven fantasy RPG Exit Exit to menu diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java index bc1b866..b313b77 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java @@ -12,7 +12,7 @@ import com.gpl.rpg.AndorsTrail.model.item.Loot; import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; import com.gpl.rpg.AndorsTrail.model.map.MapObject; import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; -import com.gpl.rpg.AndorsTrail.model.map.TMXMapReader; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapTranslator; import com.gpl.rpg.AndorsTrail.util.Coord; import com.gpl.rpg.AndorsTrail.util.L; import com.gpl.rpg.AndorsTrail.util.TimedMessageTask; @@ -242,7 +242,7 @@ public final class MovementController implements TimedMessageTask.Callback { } public static void loadCurrentTileMap(Resources res, WorldContext world) { - world.model.currentTileMap = TMXMapReader.readLayeredTileMap(res, world.tileStore, world.model.currentMap); + world.model.currentTileMap = TMXMapTranslator.readLayeredTileMap(res, world.tileStore, world.model.currentMap); } private int movementDx; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapReader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapFileParser.java similarity index 50% rename from AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapReader.java rename to AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapFileParser.java index dd196e0..2b309cc 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapReader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapFileParser.java @@ -3,42 +3,34 @@ package com.gpl.rpg.AndorsTrail.model.map; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; import org.xmlpull.v1.XmlPullParserException; -import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; -import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; -import com.gpl.rpg.AndorsTrail.model.actor.MonsterTypeCollection; -import com.gpl.rpg.AndorsTrail.model.item.DropList; -import com.gpl.rpg.AndorsTrail.model.item.DropListCollection; -import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; -import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader; -import com.gpl.rpg.AndorsTrail.resource.TileStore; import com.gpl.rpg.AndorsTrail.util.Base64; -import com.gpl.rpg.AndorsTrail.util.Coord; -import com.gpl.rpg.AndorsTrail.util.CoordRect; import com.gpl.rpg.AndorsTrail.util.L; -import com.gpl.rpg.AndorsTrail.util.Range; -import com.gpl.rpg.AndorsTrail.util.Size; import android.content.res.Resources; import android.content.res.XmlResourceParser; -public final class TMXMapReader { - private ArrayList maps = new ArrayList(); +public final class TMXMapFileParser { + public static TMXMap read(Resources r, int xmlResourceId, String name) { + return read(r.getXml(xmlResourceId), xmlResourceId, name); + } - public void read(Resources r, int xmlResourceId, String name) { - read(r.getXml(xmlResourceId), xmlResourceId, name); + public static TMXLayerMap readLayeredTileMap(Resources r, int xmlResourceId, String name) { + return readLayerMap(r.getXml(xmlResourceId), name); } - private TMXMap read(XmlResourceParser xrp, int xmlResourceId, String name) { + + private static TMXMap read(XmlResourceParser xrp, int xmlResourceId, String name) { final TMXMap map = new TMXMap(); map.xmlResourceId = xmlResourceId; try { // Map format: http://sourceforge.net/apps/mediawiki/tiled/index.php?title=Examining_the_map_format int eventType; + final ArrayList layers = new ArrayList(); + final ArrayList tileSets = new ArrayList(); while ((eventType = xrp.next()) != XmlResourceParser.END_DOCUMENT) { if (eventType == XmlResourceParser.START_TAG) { String s = xrp.getName(); @@ -52,11 +44,11 @@ public final class TMXMapReader { readCurrentTagUntilEnd(xrp, new TagHandler() { public void handleTag(XmlResourceParser xrp, String tagName) throws XmlPullParserException, IOException { if (tagName.equals("tileset")) { - map.tileSets.add(readTMXTileSet(xrp)); + tileSets.add(readTMXTileSet(xrp)); } else if (tagName.equals("objectgroup")) { map.objectGroups.add(readTMXObjectGroup(xrp)); } else if (tagName.equals("layer")) { - map.layers.add(readTMXMapLayer(xrp)); + layers.add(readTMXMapLayer(xrp)); } } }); @@ -64,19 +56,23 @@ public final class TMXMapReader { } } xrp.close(); + map.layers = layers.toArray(new TMXLayer[layers.size()]); + map.tileSets = tileSets.toArray(new TMXTileSet[tileSets.size()]); } catch (XmlPullParserException e) { L.log("Error reading map \"" + name + "\": XmlPullParserException : " + e.toString()); } catch (IOException e) { L.log("Error reading map \"" + name + "\": IOException : " + e.toString()); } - maps.add(map); return map; } - private static void readLayerMap(XmlResourceParser xrp, final String name, final TMXLayerMap map) { + private static TMXLayerMap readLayerMap(XmlResourceParser xrp, final String name) { + TMXLayerMap map = new TMXLayerMap(); try { int eventType; + final ArrayList layers = new ArrayList(); + final ArrayList tileSets = new ArrayList(); while ((eventType = xrp.next()) != XmlResourceParser.END_DOCUMENT) { if (eventType == XmlResourceParser.START_TAG) { String s = xrp.getName(); @@ -86,9 +82,9 @@ public final class TMXMapReader { readCurrentTagUntilEnd(xrp, new TagHandler() { public void handleTag(XmlResourceParser xrp, String tagName) throws XmlPullParserException, IOException { if (tagName.equals("tileset")) { - map.tileSets.add(readTMXTileSet(xrp)); + tileSets.add(readTMXTileSet(xrp)); } else if (tagName.equals("layer")) { - map.layers.add(readTMXMapLayer(xrp)); + layers.add(readTMXMapLayer(xrp)); } } }); @@ -96,11 +92,14 @@ public final class TMXMapReader { } } xrp.close(); + map.layers = layers.toArray(new TMXLayer[layers.size()]); + map.tileSets = tileSets.toArray(new TMXTileSet[tileSets.size()]); } catch (XmlPullParserException e) { L.log("Error reading layered map \"" + name + "\": XmlPullParserException : " + e.toString()); } catch (IOException e) { L.log("Error reading layered map \"" + name + "\": IOException : " + e.toString()); } + return map; } @@ -258,227 +257,6 @@ public final class TMXMapReader { (buffer[offset + 3] << 24) & 0xff000000; } - public ArrayList transformMaps(DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) { - return transformMaps(maps, tileLoader, monsterTypes, dropLists); - } - public ArrayList transformMaps(Collection maps, DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) { - ArrayList result = new ArrayList(); - - for (TMXMap m : maps) { - assert(m.name != null); - assert(m.name.length() > 0); - assert(m.width > 0); - assert(m.height > 0); - - boolean[][] isWalkable = new boolean[m.width][m.height]; - for (int y = 0; y < m.height; ++y) { - for (int x = 0; x < m.width; ++x) { - isWalkable[x][y] = true; - } - } - final Size mapSize = new Size(m.width, m.height); - for (TMXLayer layer : m.layers) { - String layerName = layer.name; - assert(layerName != null); - assert(layerName.length() > 0); - layerName = layerName.toLowerCase(); - - for (int y = 0; y < layer.height; ++y) { - for (int x = 0; x < layer.width; ++x) { - int gid = layer.gids[x][y]; - if (gid <= 0) continue; - - if (layerName.startsWith("walk")) { - isWalkable[x][y] = false; - } else { - Pair p = getTile(m, gid); - if (p == null) continue; - - String tilesetName = (String) p.first; - int localId = (Integer) p.second; - tileLoader.prepareTileID(tilesetName, localId); - } - } - } - } - - ArrayList mapObjects = new ArrayList(); - ArrayList spawnAreas = new ArrayList(); - - for (TMXObjectGroup group : m.objectGroups) { - for (TMXObject object : group.objects) { - final Coord topLeft = new Coord( - Math.round(((float)object.x) / m.tilewidth) - ,Math.round(((float)object.y) / m.tileheight) - ); - final int width = Math.round(((float)object.width) / m.tilewidth); - final int height = Math.round(((float)object.height) / m.tileheight); - final CoordRect position = new CoordRect(topLeft, new Size(width, height)); - - if (object.type == null) { - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) - L.log("WARNING: Map " + m.name + ", object \"" + object.name + "\" has null type."); - } else if (object.type.equalsIgnoreCase("sign")) { - String phraseID = object.name; - for (TMXProperty p : object.properties) { - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + ", sign " + object.name + " has unrecognized property \"" + p.name + "\"."); - } - mapObjects.add(MapObject.createMapSignEvent(position, phraseID)); - } else if (object.type.equalsIgnoreCase("mapchange")) { - String map = null; - String place = null; - for (TMXProperty p : object.properties) { - if(p.name.equalsIgnoreCase("map")) map = p.value; - else if(p.name.equalsIgnoreCase("place")) place = p.value; - else if(AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + ", mapchange " + object.name + " has unrecognized property \"" + p.name + "\"."); - } - mapObjects.add(MapObject.createNewMapEvent(position, object.name, map, place)); - } else if (object.type.equalsIgnoreCase("spawn")) { - ArrayList types = monsterTypes.getMonsterTypesFromSpawnGroup(object.name); - int maxQuantity = 1; - int spawnChance = 10; - boolean isUnique = false; - for (TMXProperty p : object.properties) { - if (p.name.equalsIgnoreCase("quantity")) { - maxQuantity = Integer.parseInt(p.value); - } else if (p.name.equalsIgnoreCase("spawnchance")) { - spawnChance = Integer.parseInt(p.value); - } else if (p.name.equalsIgnoreCase("respawn")) { - isUnique = !Boolean.parseBoolean(p.value); - } else if (p.name.equalsIgnoreCase("unique")) { - isUnique = Boolean.parseBoolean(p.value); - } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - L.log("OPTIMIZE: Map " + m.name + ", spawn " + object.name + " has unrecognized property \"" + p.name + "\"."); - } - } - - if (types.isEmpty()) { - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - L.log("OPTIMIZE: Map " + m.name + " contains spawn \"" + object.name + "\" that does not correspond to any monsters. The spawn will be removed."); - } - continue; - } - - String[] monsterTypeIDs = new String[types.size()]; - for (int i = 0; i < monsterTypeIDs.length; ++i) { - monsterTypeIDs[i] = types.get(i).id; - if (isUnique) types.get(i).isRespawnable = false; - } - MonsterSpawnArea area = new MonsterSpawnArea( - position - ,new Range(maxQuantity, 0) - ,new Range(1000, spawnChance) - ,monsterTypeIDs - ,isUnique - ); - spawnAreas.add(area); - } else if (object.type.equalsIgnoreCase("key")) { - QuestProgress requireQuestStage = QuestProgress.parseQuestProgress(object.name); - if (requireQuestStage == null) { - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - L.log("OPTIMIZE: Map " + m.name + " contains key area that cannot be parsed as a quest stage."); - } - continue; - } - String phraseID = ""; - for (TMXProperty p : object.properties) { - if (p.name.equalsIgnoreCase("phrase")) { - phraseID = p.value; - } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - L.log("OPTIMIZE: Map " + m.name + ", key " + object.name + " has unrecognized property \"" + p.name + "\"."); - } - } - - mapObjects.add(MapObject.createNewKeyArea(position, phraseID, requireQuestStage)); - } else if (object.type.equals("rest")) { - mapObjects.add(MapObject.createNewRest(position, object.name)); - } else if (object.type.equals("container")) { - DropList dropList = dropLists.getDropList(object.name); - if (dropList == null) continue; - mapObjects.add(MapObject.createNewContainerArea(position, dropList)); - } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - L.log("OPTIMIZE: Map " + m.name + ", has unrecognized object type \"" + object.type + "\" for name \"" + object.name + "\"."); - } - } - } - MapObject[] _eventObjects = new MapObject[mapObjects.size()]; - _eventObjects = mapObjects.toArray(_eventObjects); - MonsterSpawnArea[] _spawnAreas = new MonsterSpawnArea[spawnAreas.size()]; - _spawnAreas = spawnAreas.toArray(_spawnAreas); - - result.add(new PredefinedMap(m.xmlResourceId, m.name, mapSize, isWalkable, _eventObjects, _spawnAreas, false)); - } - - return result; - } - - - private static LayeredTileMap transformMap(TMXLayerMap map, TileStore tileStore) { - final Size mapSize = new Size(map.width, map.height); - final MapLayer[] layers = new MapLayer[] { - new MapLayer(mapSize) - ,new MapLayer(mapSize) - ,new MapLayer(mapSize) - }; - for (TMXLayer layer : map.layers) { - int ixMapLayer = -2; - String layerName = layer.name; - assert(layerName != null); - assert(layerName.length() > 0); - layerName = layerName.toLowerCase(); - if (layerName.startsWith("object")) { - ixMapLayer = LayeredTileMap.LAYER_OBJECTS; - } else if (layerName.startsWith("ground")) { - ixMapLayer = LayeredTileMap.LAYER_GROUND; - } else if (layerName.startsWith("above")) { - ixMapLayer = LayeredTileMap.LAYER_ABOVE; - } else { - continue; - } - - for (int y = 0; y < layer.height; ++y) { - for (int x = 0; x < layer.width; ++x) { - int gid = layer.gids[x][y]; - if (gid <= 0) continue; - - Pair p = getTile(map, gid); - if (p == null) continue; - - String tilesetName = (String) p.first; - int localId = (Integer) p.second; - layers[ixMapLayer].tiles[x][y] = tileStore.getTileID(tilesetName, localId); - } - } - } - return new LayeredTileMap(mapSize, layers); - } - - public static LayeredTileMap readLayeredTileMap(Resources res, TileStore tileStore, PredefinedMap map) { - TMXLayerMap result = new TMXLayerMap(); - readLayerMap(res.getXml(map.xmlResourceId), map.name, result); - return transformMap(result, tileStore); - } - - private static Pair getTile(final TMXLayerMap map, final int gid) { - for(int i = map.tileSets.size() - 1; i >= 0; --i) { - TMXTileSet ts = map.tileSets.get(i); - if (ts.firstgid <= gid) { - return new Pair(ts.imageName, (gid - ts.firstgid)); - } - } - L.log("WARNING: Cannot find tile for gid " + gid); //(" + x + ", " + y + "), ") - return null; - } - - private static final class Pair { - public final T1 first; - public final T2 second; - public Pair(T1 first, T2 second) { - this.first = first; - this.second = second; - } - } - public static final class TMXMap extends TMXLayerMap { public int xmlResourceId; public String name; @@ -490,8 +268,8 @@ public final class TMXMapReader { public static class TMXLayerMap { public int width; public int height; - public ArrayList tileSets = new ArrayList(); - public ArrayList layers = new ArrayList(); + public TMXTileSet[] tileSets; + public TMXLayer[] layers; } public static final class TMXTileSet { public int firstgid; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java new file mode 100644 index 0000000..8f27d9e --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java @@ -0,0 +1,319 @@ +package com.gpl.rpg.AndorsTrail.model.map; + +import java.util.ArrayList; +import java.util.Collection; + +import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; +import com.gpl.rpg.AndorsTrail.model.actor.MonsterTypeCollection; +import com.gpl.rpg.AndorsTrail.model.item.DropList; +import com.gpl.rpg.AndorsTrail.model.item.DropListCollection; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXLayer; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXLayerMap; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXMap; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObject; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXObjectGroup; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXProperty; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.TMXTileSet; +import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; +import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader; +import com.gpl.rpg.AndorsTrail.resource.TileStore; +import com.gpl.rpg.AndorsTrail.util.Coord; +import com.gpl.rpg.AndorsTrail.util.CoordRect; +import com.gpl.rpg.AndorsTrail.util.L; +import com.gpl.rpg.AndorsTrail.util.Range; +import com.gpl.rpg.AndorsTrail.util.Size; + +import android.content.res.Resources; + +public final class TMXMapTranslator { + private ArrayList maps = new ArrayList(); + + public void read(Resources r, int xmlResourceId, String name) { + maps.add(TMXMapFileParser.read(r, xmlResourceId, name)); + } + + public static LayeredTileMap readLayeredTileMap(Resources res, TileStore tileStore, PredefinedMap map) { + TMXLayerMap resultMap = TMXMapFileParser.readLayeredTileMap(res, map.xmlResourceId, map.name); + return transformMap(resultMap, tileStore); + } + + public ArrayList transformMaps(DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) { + return transformMaps(maps, tileLoader, monsterTypes, dropLists); + } + public ArrayList transformMaps(Collection maps, DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) { + ArrayList result = new ArrayList(); + + Tile tile = new Tile(); + for (TMXMap m : maps) { + assert(m.name != null); + assert(m.name.length() > 0); + assert(m.width > 0); + assert(m.height > 0); + + boolean[][] isWalkable = new boolean[m.width][m.height]; + for (int y = 0; y < m.height; ++y) { + for (int x = 0; x < m.width; ++x) { + isWalkable[x][y] = true; + } + } + final Size mapSize = new Size(m.width, m.height); + for (TMXLayer layer : m.layers) { + String layerName = layer.name; + assert(layerName != null); + assert(layerName.length() > 0); + layerName = layerName.toLowerCase(); + + boolean isWalkableLayer = layerName.startsWith("walk"); + + for (int y = 0; y < layer.height; ++y) { + for (int x = 0; x < layer.width; ++x) { + int gid = layer.gids[x][y]; + if (gid <= 0) continue; + + if (isWalkableLayer) { + isWalkable[x][y] = false; + } else { + if (!getTile(m, gid, tile)) continue; + tileLoader.prepareTileID(tile.tilesetName, tile.localId); + } + } + } + } + + ArrayList mapObjects = new ArrayList(); + ArrayList spawnAreas = new ArrayList(); + + for (TMXObjectGroup group : m.objectGroups) { + for (TMXObject object : group.objects) { + final Coord topLeft = new Coord( + Math.round(((float)object.x) / m.tilewidth) + ,Math.round(((float)object.y) / m.tileheight) + ); + final int width = Math.round(((float)object.width) / m.tilewidth); + final int height = Math.round(((float)object.height) / m.tileheight); + final CoordRect position = new CoordRect(topLeft, new Size(width, height)); + + if (object.type == null) { + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) + L.log("WARNING: Map " + m.name + ", object \"" + object.name + "\" has null type."); + } else if (object.type.equalsIgnoreCase("sign")) { + String phraseID = object.name; + for (TMXProperty p : object.properties) { + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + ", sign " + object.name + " has unrecognized property \"" + p.name + "\"."); + } + mapObjects.add(MapObject.createMapSignEvent(position, phraseID)); + } else if (object.type.equalsIgnoreCase("mapchange")) { + String map = null; + String place = null; + for (TMXProperty p : object.properties) { + if(p.name.equalsIgnoreCase("map")) map = p.value; + else if(p.name.equalsIgnoreCase("place")) place = p.value; + else if(AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) L.log("OPTIMIZE: Map " + m.name + ", mapchange " + object.name + " has unrecognized property \"" + p.name + "\"."); + } + mapObjects.add(MapObject.createNewMapEvent(position, object.name, map, place)); + } else if (object.type.equalsIgnoreCase("spawn")) { + ArrayList types = monsterTypes.getMonsterTypesFromSpawnGroup(object.name); + int maxQuantity = 1; + int spawnChance = 10; + boolean isUnique = false; + for (TMXProperty p : object.properties) { + if (p.name.equalsIgnoreCase("quantity")) { + maxQuantity = Integer.parseInt(p.value); + } else if (p.name.equalsIgnoreCase("spawnchance")) { + spawnChance = Integer.parseInt(p.value); + } else if (p.name.equalsIgnoreCase("respawn")) { + isUnique = !Boolean.parseBoolean(p.value); + } else if (p.name.equalsIgnoreCase("unique")) { + isUnique = Boolean.parseBoolean(p.value); + } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + L.log("OPTIMIZE: Map " + m.name + ", spawn " + object.name + " has unrecognized property \"" + p.name + "\"."); + } + } + + if (types.isEmpty()) { + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + L.log("OPTIMIZE: Map " + m.name + " contains spawn \"" + object.name + "\" that does not correspond to any monsters. The spawn will be removed."); + } + continue; + } + + String[] monsterTypeIDs = new String[types.size()]; + for (int i = 0; i < monsterTypeIDs.length; ++i) { + monsterTypeIDs[i] = types.get(i).id; + if (isUnique) types.get(i).isRespawnable = false; + } + MonsterSpawnArea area = new MonsterSpawnArea( + position + ,new Range(maxQuantity, 0) + ,new Range(1000, spawnChance) + ,monsterTypeIDs + ,isUnique + ); + spawnAreas.add(area); + } else if (object.type.equalsIgnoreCase("key")) { + QuestProgress requireQuestStage = QuestProgress.parseQuestProgress(object.name); + if (requireQuestStage == null) { + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + L.log("OPTIMIZE: Map " + m.name + " contains key area that cannot be parsed as a quest stage."); + } + continue; + } + String phraseID = ""; + for (TMXProperty p : object.properties) { + if (p.name.equalsIgnoreCase("phrase")) { + phraseID = p.value; + } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + L.log("OPTIMIZE: Map " + m.name + ", key " + object.name + " has unrecognized property \"" + p.name + "\"."); + } + } + + mapObjects.add(MapObject.createNewKeyArea(position, phraseID, requireQuestStage)); + } else if (object.type.equals("rest")) { + mapObjects.add(MapObject.createNewRest(position, object.name)); + } else if (object.type.equals("container")) { + DropList dropList = dropLists.getDropList(object.name); + if (dropList == null) continue; + mapObjects.add(MapObject.createNewContainerArea(position, dropList)); + } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + L.log("OPTIMIZE: Map " + m.name + ", has unrecognized object type \"" + object.type + "\" for name \"" + object.name + "\"."); + } + } + } + MapObject[] _eventObjects = new MapObject[mapObjects.size()]; + _eventObjects = mapObjects.toArray(_eventObjects); + MonsterSpawnArea[] _spawnAreas = new MonsterSpawnArea[spawnAreas.size()]; + _spawnAreas = spawnAreas.toArray(_spawnAreas); + + result.add(new PredefinedMap(m.xmlResourceId, m.name, mapSize, isWalkable, _eventObjects, _spawnAreas, false)); + } + + return result; + } + + + private static LayeredTileMap transformMap(TMXLayerMap map, TileStore tileStore) { + final Size mapSize = new Size(map.width, map.height); + final MapLayer[] layers = new MapLayer[] { + new MapLayer(mapSize) + ,new MapLayer(mapSize) + ,new MapLayer(mapSize) + }; + Tile tile = new Tile(); + for (TMXLayer layer : map.layers) { + int ixMapLayer = -2; + String layerName = layer.name; + assert(layerName != null); + assert(layerName.length() > 0); + layerName = layerName.toLowerCase(); + if (layerName.startsWith("object")) { + ixMapLayer = LayeredTileMap.LAYER_OBJECTS; + } else if (layerName.startsWith("ground")) { + ixMapLayer = LayeredTileMap.LAYER_GROUND; + } else if (layerName.startsWith("above")) { + ixMapLayer = LayeredTileMap.LAYER_ABOVE; + } else { + continue; + } + + for (int y = 0; y < layer.height; ++y) { + for (int x = 0; x < layer.width; ++x) { + int gid = layer.gids[x][y]; + if (gid <= 0) continue; + + if (!getTile(map, gid, tile)) continue; + + layers[ixMapLayer].tiles[x][y] = tileStore.getTileID(tile.tilesetName, tile.localId); + } + } + } + return new LayeredTileMap(mapSize, layers); + } + + private static boolean getTile(final TMXLayerMap map, final int gid, final Tile dest) { + for(int i = map.tileSets.length - 1; i >= 0; --i) { + TMXTileSet ts = map.tileSets[i]; + if (ts.firstgid <= gid) { + dest.tilesetName = ts.imageName; + dest.localId = (gid - ts.firstgid); + return true; + } + } + L.log("WARNING: Cannot find tile for gid " + gid); //(" + x + ", " + y + "), ") + return false; + } + + private static final class Tile { + public String tilesetName; + public int localId; + } + + /* + public static final class TMXMap extends TMXLayerMap { + public int xmlResourceId; + public String name; + public String orientation; + public int tilewidth; + public int tileheight; + public ArrayList objectGroups = new ArrayList(); + } + public static class TMXLayerMap { + public int width; + public int height; + public TMXTileSet[] tileSets; + public TMXLayer[] layers; + } + public static final class TMXTileSet { + public int firstgid; + public String name; + public int tilewidth; + public int tileheight; + public String imageSource; + public String imageName; + } + public static final class TMXLayer { + public String name; + public int width; + public int height; + public int[][] gids; + } + public static final class TMXObjectGroup { + public String name; + public int width; + public int height; + public ArrayList objects = new ArrayList(); + } + public static final class TMXObject { + public String name; + public String type; + public int x; + public int y; + public int width; + public int height; + public ArrayList properties = new ArrayList(); + } + public static final class TMXProperty { + public String name; + public String value; + } + */ + /* + + + + + + + + H4sIAAAAAAAAA/NgYGDwIBK7AbEnHkyOOmwYXR02MwZSHQyTah4xGADnAt2SkAEAAA== + + + + + H4sIAAAAAAAAA2NgoA1gYUHlP2HGro6NBbt4MysqXw2oLhEqlgSlU4H0YjR12EAbUE0KFnXPgG5iRLJ/GQ6zHuNwOy7gxE6aemQAAJRT7VKQAQAA + + + + + */ +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java index 5e1df31..b58a6d6 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java @@ -3,7 +3,7 @@ package com.gpl.rpg.AndorsTrail.resource; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.R; import com.gpl.rpg.AndorsTrail.context.WorldContext; -import com.gpl.rpg.AndorsTrail.model.map.TMXMapReader; +import com.gpl.rpg.AndorsTrail.model.map.TMXMapTranslator; import com.gpl.rpg.AndorsTrail.resource.parsers.ActorConditionsTypeParser; import com.gpl.rpg.AndorsTrail.resource.parsers.ConversationListParser; import com.gpl.rpg.AndorsTrail.resource.parsers.DropListParser; @@ -135,7 +135,7 @@ public final class ResourceLoader { // ======================================================================== // Load maps - TMXMapReader mapReader = new TMXMapReader(); + TMXMapTranslator mapReader = new TMXMapTranslator(); final TypedArray mapsToLoad = r.obtainTypedArray(mapsResourceId); for (int i = 0; i < mapsToLoad.length(); ++i) { final int mapResourceId = mapsToLoad.getResourceId(i, -1); -- 2.49.0