mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-01-06 19:50:01 +01:00
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
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
android:name=".AndorsTrailApplication"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:description="@string/app_description"
|
||||
>
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
|
||||
@@ -2901,7 +2901,7 @@
|
||||
{Here\'s 2000 gold, take it.|buceth_gold_yes||gold|2000|}
|
||||
}|};
|
||||
{buceth_gold_no|Hrmpf. Thanks for the gold, but I am not interested in talking to you. Now, please leave.||||};
|
||||
{buceth_gold_yes|You seem to realize the true value of the Shadow. Yes, this will do fine, thank you.|loneford:41||{{N|buceth_bribed_1||||}}|};
|
||||
{buceth_gold_yes|You seem to realize the true value of the Shadow. Yes, this will do fine, thank you.|loneford:41||{{N|buceth_story_1||||}}|};
|
||||
{buceth_5|Let\'s assume you live in a village that, for the most part, keeps to itself. Your village is self-sustainable and the crops have been good for some years.|||{{N|buceth_6||||}}|};
|
||||
{buceth_6|With the few exceptions of a some fights here and there between villagers because of misunderstandings, on the whole, your village is a friendly peaceful village.|||{{N|buceth_7||||}}|};
|
||||
{buceth_7|You work in the same profession as your parents, which in turn worked in the same professions as their parents.|||{{N|buceth_8||||}}|};
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
|
||||
<string name="droplists_crossglen_outside">
|
||||
[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|}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<resources>
|
||||
<string name="app_name">Andor\'s Trail</string>
|
||||
<string name="app_description">Quest-driven fantasy RPG</string>
|
||||
|
||||
<string name="exit">Exit</string>
|
||||
<string name="exit_to_menu">Exit to menu</string>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<TMXMap> maps = new ArrayList<TMXMap>();
|
||||
|
||||
public void read(Resources r, int xmlResourceId, String name) {
|
||||
read(r.getXml(xmlResourceId), xmlResourceId, name);
|
||||
public final class TMXMapFileParser {
|
||||
public static TMXMap read(Resources r, int xmlResourceId, String name) {
|
||||
return read(r.getXml(xmlResourceId), xmlResourceId, name);
|
||||
}
|
||||
private TMXMap read(XmlResourceParser xrp, int xmlResourceId, String name) {
|
||||
|
||||
public static TMXLayerMap readLayeredTileMap(Resources r, int xmlResourceId, String name) {
|
||||
return readLayerMap(r.getXml(xmlResourceId), 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<TMXLayer> layers = new ArrayList<TMXLayer>();
|
||||
final ArrayList<TMXTileSet> tileSets = new ArrayList<TMXTileSet>();
|
||||
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<TMXLayer> layers = new ArrayList<TMXLayer>();
|
||||
final ArrayList<TMXTileSet> tileSets = new ArrayList<TMXTileSet>();
|
||||
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<PredefinedMap> transformMaps(DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
|
||||
return transformMaps(maps, tileLoader, monsterTypes, dropLists);
|
||||
}
|
||||
public ArrayList<PredefinedMap> transformMaps(Collection<TMXMap> maps, DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
|
||||
ArrayList<PredefinedMap> result = new ArrayList<PredefinedMap>();
|
||||
|
||||
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<String, Integer> p = getTile(m, gid);
|
||||
if (p == null) continue;
|
||||
|
||||
String tilesetName = (String) p.first;
|
||||
int localId = (Integer) p.second;
|
||||
tileLoader.prepareTileID(tilesetName, localId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<MapObject> mapObjects = new ArrayList<MapObject>();
|
||||
ArrayList<MonsterSpawnArea> spawnAreas = new ArrayList<MonsterSpawnArea>();
|
||||
|
||||
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<MonsterType> 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<String, Integer> 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<String, Integer> 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<String, Integer>(ts.imageName, (gid - ts.firstgid));
|
||||
}
|
||||
}
|
||||
L.log("WARNING: Cannot find tile for gid " + gid); //(" + x + ", " + y + "), ")
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class Pair<T1, T2> {
|
||||
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<TMXTileSet> tileSets = new ArrayList<TMXTileSet>();
|
||||
public ArrayList<TMXLayer> layers = new ArrayList<TMXLayer>();
|
||||
public TMXTileSet[] tileSets;
|
||||
public TMXLayer[] layers;
|
||||
}
|
||||
public static final class TMXTileSet {
|
||||
public int firstgid;
|
||||
@@ -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<TMXMap> maps = new ArrayList<TMXMap>();
|
||||
|
||||
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<PredefinedMap> transformMaps(DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
|
||||
return transformMaps(maps, tileLoader, monsterTypes, dropLists);
|
||||
}
|
||||
public ArrayList<PredefinedMap> transformMaps(Collection<TMXMap> maps, DynamicTileLoader tileLoader, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
|
||||
ArrayList<PredefinedMap> result = new ArrayList<PredefinedMap>();
|
||||
|
||||
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<MapObject> mapObjects = new ArrayList<MapObject>();
|
||||
ArrayList<MonsterSpawnArea> spawnAreas = new ArrayList<MonsterSpawnArea>();
|
||||
|
||||
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<MonsterType> 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<TMXObjectGroup> objectGroups = new ArrayList<TMXObjectGroup>();
|
||||
}
|
||||
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<TMXObject> objects = new ArrayList<TMXObject>();
|
||||
}
|
||||
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<TMXProperty> properties = new ArrayList<TMXProperty>();
|
||||
}
|
||||
public static final class TMXProperty {
|
||||
public String name;
|
||||
public String value;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
|
||||
<map version="1.0" orientation="orthogonal" width="10" height="10" tilewidth="32" tileheight="32">
|
||||
<tileset firstgid="1" name="tiles" tilewidth="32" tileheight="32">
|
||||
<image source="tilesets/tiles.png"/>
|
||||
</tileset>
|
||||
<layer name="Tile Layer 1" width="10" height="10">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAAA/NgYGDwIBK7AbEnHkyOOmwYXR02MwZSHQyTah4xGADnAt2SkAEAAA==
|
||||
</data>
|
||||
</layer>
|
||||
<layer name="Tile Layer 2" width="10" height="10">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAAA2NgoA1gYUHlP2HGro6NBbt4MysqXw2oLhEqlgSlU4H0YjR12EAbUE0KFnXPgG5iRLJ/GQ6zHuNwOy7gxE6aemQAAJRT7VKQAQAA
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
||||
|
||||
*/
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user