mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-02-23 15:38:29 +01:00
Merge branch 'dynamic-layeredtilemap'
This commit is contained in:
@@ -1,125 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE map SYSTEM "http://mapeditor.org/dtd/1.0/map.dtd">
|
||||
<map version="1.0" orientation="orthogonal" width="30" height="30" tilewidth="32" tileheight="32">
|
||||
<tileset firstgid="1" name="map_bed_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_bed_1.png"/>
|
||||
<image source="../drawable/map_bed_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="129" name="map_border_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_border_1.png"/>
|
||||
<image source="../drawable/map_border_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="257" name="map_bridge_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_bridge_1.png"/>
|
||||
<image source="../drawable/map_bridge_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="385" name="map_broken_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_broken_1.png"/>
|
||||
<image source="../drawable/map_broken_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="513" name="map_cavewall_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_cavewall_1.png"/>
|
||||
<image source="../drawable/map_cavewall_1.png" width="576" height="192"/>
|
||||
</tileset>
|
||||
<tileset firstgid="621" name="map_cavewall_2" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_cavewall_2.png"/>
|
||||
<image source="../drawable/map_cavewall_2.png" width="576" height="192"/>
|
||||
</tileset>
|
||||
<tileset firstgid="729" name="map_cavewall_3" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_cavewall_3.png"/>
|
||||
<image source="../drawable/map_cavewall_3.png" width="576" height="192"/>
|
||||
</tileset>
|
||||
<tileset firstgid="837" name="map_chair_table_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_chair_table_1.png"/>
|
||||
<image source="../drawable/map_chair_table_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="965" name="map_crate_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_crate_1.png"/>
|
||||
<image source="../drawable/map_crate_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1093" name="map_cupboard_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_cupboard_1.png"/>
|
||||
<image source="../drawable/map_cupboard_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1221" name="map_curtain_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_curtain_1.png"/>
|
||||
<image source="../drawable/map_curtain_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1349" name="map_entrance_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_entrance_1.png"/>
|
||||
<image source="../drawable/map_entrance_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1477" name="map_fence_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_fence_1.png"/>
|
||||
<image source="../drawable/map_fence_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1605" name="map_fence_2" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_fence_2.png"/>
|
||||
<image source="../drawable/map_fence_2.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1733" name="map_ground_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_1.png"/>
|
||||
<image source="../drawable/map_ground_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1861" name="map_ground_2" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_2.png"/>
|
||||
<image source="../drawable/map_ground_2.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="1989" name="map_ground_3" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_3.png"/>
|
||||
<image source="../drawable/map_ground_3.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2117" name="map_ground_4" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_4.png"/>
|
||||
<image source="../drawable/map_ground_4.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2245" name="map_ground_5" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_5.png"/>
|
||||
<image source="../drawable/map_ground_5.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2373" name="map_ground_6" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_6.png"/>
|
||||
<image source="../drawable/map_ground_6.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2501" name="map_ground_7" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_7.png"/>
|
||||
<image source="../drawable/map_ground_7.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2629" name="map_ground_8" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_ground_8.png"/>
|
||||
<image source="../drawable/map_ground_8.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2757" name="map_indoor_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_indoor_1.png"/>
|
||||
<image source="../drawable/map_indoor_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2885" name="map_kitchen_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_kitchen_1.png"/>
|
||||
<image source="../drawable/map_kitchen_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3013" name="map_outdoor_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_outdoor_1.png"/>
|
||||
<image source="../drawable/map_outdoor_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3141" name="map_pillar_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_pillar_1.png"/>
|
||||
<image source="../drawable/map_pillar_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3269" name="map_plant_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_plant_1.png"/>
|
||||
<image source="../drawable/map_plant_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3397" name="map_rock_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_rock_1.png"/>
|
||||
<image source="../drawable/map_rock_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3525" name="map_roof_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_roof_1.png"/>
|
||||
<image source="../drawable/map_roof_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3653" name="map_roof_2" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_roof_2.png"/>
|
||||
<image source="../drawable/map_roof_2.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3781" name="map_shop_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_shop_1.png"/>
|
||||
<image source="../drawable/map_shop_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="3909" name="map_sign_ladder_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_sign_ladder_1.png"/>
|
||||
<image source="../drawable/map_sign_ladder_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4037" name="map_table_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_table_1.png"/>
|
||||
<image source="../drawable/map_table_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4165" name="map_trail_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_trail_1.png"/>
|
||||
<image source="../drawable/map_trail_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4293" name="map_tree_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_tree_1.png"/>
|
||||
<image source="../drawable/map_tree_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4421" name="map_wall_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_wall_1.png"/>
|
||||
<image source="../drawable/map_wall_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4549" name="map_wall_2" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_wall_2.png"/>
|
||||
<image source="../drawable/map_wall_2.png" width="480" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4669" name="map_wall_3" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_wall_3.png"/>
|
||||
<image source="../drawable/map_wall_3.png" width="480" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4789" name="map_window_1" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_window_1.png"/>
|
||||
<image source="../drawable/map_window_1.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="4917" name="map_window_2" tilewidth="32" tileheight="32">
|
||||
<image source="../drawable/map_window_2.png"/>
|
||||
<image source="../drawable/map_window_2.png" width="512" height="256"/>
|
||||
</tileset>
|
||||
<layer name="Ground" width="30" height="30">
|
||||
<data encoding="base64" compression="zlib">
|
||||
@@ -144,4 +143,5 @@
|
||||
<objectgroup name="Mapevents" width="30" height="30"/>
|
||||
<objectgroup name="Spawn" width="30" height="30"/>
|
||||
<objectgroup name="Keys" width="30" height="30"/>
|
||||
<objectgroup name="Replace" width="30" height="30"/>
|
||||
</map>
|
||||
|
||||
@@ -18,7 +18,7 @@ public final class AndorsTrailApplication extends Application {
|
||||
public static final boolean DEVELOPMENT_VALIDATEDATA = true;
|
||||
public static final boolean DEVELOPMENT_DEBUGMESSAGES = true;
|
||||
public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = DEVELOPMENT_DEBUGRESOURCES;
|
||||
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? 999 : 35;
|
||||
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? 999 : 36;
|
||||
public static final String CURRENT_VERSION_DISPLAY = "0.7.0dev";
|
||||
|
||||
private final AndorsTrailPreferences preferences = new AndorsTrailPreferences();
|
||||
|
||||
@@ -121,6 +121,7 @@ public final class MainActivity extends Activity implements PlayerMovementListen
|
||||
break;
|
||||
case INTENTREQUEST_CONVERSATION:
|
||||
MovementController.refreshMonsterAggressiveness(world.model.currentMap, world.model.player);
|
||||
controllers.mapController.applyCurrentMapReplacements(getResources(), true);
|
||||
break;
|
||||
case INTENTREQUEST_SAVEGAME:
|
||||
if (resultCode != Activity.RESULT_OK) break;
|
||||
@@ -138,15 +139,26 @@ public final class MainActivity extends Activity implements PlayerMovementListen
|
||||
final Player player = world.model.player;
|
||||
return Savegames.saveWorld(world, this, slot, getString(R.string.savegame_currenthero_displayinfo, player.getLevel(), player.getTotalExperience(), player.getGold()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (!AndorsTrailApplication.getApplicationFromActivity(this).getWorldSetup().isSceneReady) return;
|
||||
subscribeToModelChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
unsubscribeFromModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
controllers.gameRoundController.pause();
|
||||
controllers.movementController.stopMovement();
|
||||
|
||||
unsubscribeFromModel();
|
||||
|
||||
save(Savegames.SLOT_QUICKSAVE);
|
||||
}
|
||||
|
||||
@@ -155,8 +167,6 @@ public final class MainActivity extends Activity implements PlayerMovementListen
|
||||
super.onResume();
|
||||
if (!AndorsTrailApplication.getApplicationFromActivity(this).getWorldSetup().isSceneReady) return;
|
||||
|
||||
subscribeToModelChanges();
|
||||
|
||||
controllers.gameRoundController.resume();
|
||||
|
||||
if (world.model.uiSelections.isInCombat) {
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.gpl.rpg.AndorsTrail.model.item.Loot;
|
||||
import com.gpl.rpg.AndorsTrail.model.quest.QuestLogEntry;
|
||||
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
|
||||
import com.gpl.rpg.AndorsTrail.util.ConstRange;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.Collection;
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
|
||||
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.listeners.LootBagListeners;
|
||||
import com.gpl.rpg.AndorsTrail.controller.listeners.QuickSlotListeners;
|
||||
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
|
||||
@@ -23,8 +22,7 @@ public final class ItemController {
|
||||
|
||||
private final ControllerContext controllers;
|
||||
private final WorldContext world;
|
||||
public final QuickSlotListeners quickSlotListeners = new QuickSlotListeners();
|
||||
public final LootBagListeners lootBagListeners = new LootBagListeners();
|
||||
public final QuickSlotListeners quickSlotListeners = new QuickSlotListeners();
|
||||
|
||||
public ItemController(ControllerContext controllers, WorldContext world) {
|
||||
this.controllers = controllers;
|
||||
@@ -213,7 +211,7 @@ public final class ItemController {
|
||||
if (loot.hasItems()) return false;
|
||||
|
||||
world.model.currentMap.removeGroundLoot(loot);
|
||||
lootBagListeners.onLootBagRemoved(world.model.currentMap, loot.position);
|
||||
controllers.mapController.mapLayoutListeners.onLootBagRemoved(world.model.currentMap, loot.position);
|
||||
return true; // The bag was removed.
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package com.gpl.rpg.AndorsTrail.controller;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.listeners.MapLayoutListeners;
|
||||
import com.gpl.rpg.AndorsTrail.controller.listeners.WorldEventListeners;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.ReplaceableMapSection;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
|
||||
public final class MapController {
|
||||
@@ -15,6 +19,7 @@ public final class MapController {
|
||||
private final ControllerContext controllers;
|
||||
private final WorldContext world;
|
||||
public final WorldEventListeners worldEventListeners = new WorldEventListeners();
|
||||
public final MapLayoutListeners mapLayoutListeners = new MapLayoutListeners();
|
||||
|
||||
public MapController(ControllerContext controllers, WorldContext world) {
|
||||
this.controllers = controllers;
|
||||
@@ -106,4 +111,31 @@ public final class MapController {
|
||||
m.resetTemporaryData();
|
||||
}
|
||||
}
|
||||
|
||||
public void applyCurrentMapReplacements(final Resources res, boolean updateWorldmap) {
|
||||
if (!applyReplacements(world.model.currentMap, world.model.currentTileMap)) return;
|
||||
world.maps.worldMapRequiresUpdate = true;
|
||||
|
||||
if (!updateWorldmap) return;
|
||||
WorldMapController.updateWorldMap(world, res);
|
||||
mapLayoutListeners.onMapTilesChanged(world.model.currentMap, world.model.currentTileMap);
|
||||
}
|
||||
|
||||
private boolean applyReplacements(PredefinedMap map, LayeredTileMap tileMap) {
|
||||
boolean hasUpdated = false;
|
||||
if (tileMap.replacements != null) {
|
||||
for(ReplaceableMapSection replacement : tileMap.replacements) {
|
||||
if (replacement.isApplied) continue;
|
||||
if (!satisfiesCondition(replacement)) continue;
|
||||
tileMap.applyReplacement(replacement);
|
||||
hasUpdated = true;
|
||||
}
|
||||
}
|
||||
map.lastSeenLayoutHash = tileMap.getCurrentLayoutHash();
|
||||
return hasUpdated;
|
||||
}
|
||||
|
||||
public boolean satisfiesCondition(ReplaceableMapSection replacement) {
|
||||
return world.model.player.hasExactQuestProgress(replacement.requireQuestStage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
private void playerVisitsMapFirstTime(PredefinedMap m) {
|
||||
m.reset();
|
||||
m.createAllContainerLoot();
|
||||
world.maps.worldMapRequiresUpdate = true;
|
||||
}
|
||||
|
||||
public void prepareMapAsCurrentMap(PredefinedMap newMap, Resources res, boolean spawnMonsters) {
|
||||
@@ -99,10 +100,12 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
controllers.monsterSpawnController.spawnAll(newMap, model.currentTileMap);
|
||||
}
|
||||
}
|
||||
controllers.mapController.applyCurrentMapReplacements(res, false);
|
||||
newMap.visited = true;
|
||||
moveBlockedActors(newMap, model.currentTileMap);
|
||||
refreshMonsterAggressiveness(newMap, model.player);
|
||||
controllers.effectController.updateSplatters(newMap);
|
||||
WorldMapController.updateWorldMap(world, res);
|
||||
}
|
||||
|
||||
private boolean mayMovePlayer() {
|
||||
@@ -294,8 +297,6 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
world.model.currentTileMap = mapTiles;
|
||||
world.tileManager.currentMapTiles = cachedTiles;
|
||||
world.tileManager.cacheAdjacentMaps(res, world, nextMap);
|
||||
|
||||
WorldMapController.updateWorldMap(world, nextMap, mapTiles, cachedTiles, res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.*;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -22,10 +21,7 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.activity.DisplayWorldMapActivity;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.MapLayer;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.*;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
|
||||
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
|
||||
@@ -38,14 +34,22 @@ public final class WorldMapController {
|
||||
|
||||
private static final int WORLDMAP_SCREENSHOT_TILESIZE = 8;
|
||||
public static final int WORLDMAP_DISPLAY_TILESIZE = WORLDMAP_SCREENSHOT_TILESIZE;
|
||||
|
||||
public static void updateWorldMap(final WorldContext world, final PredefinedMap map, final LayeredTileMap mapTiles, final TileCollection cachedTiles, final Resources res) {
|
||||
|
||||
|
||||
public static void updateWorldMap(final WorldContext world, final Resources res) {
|
||||
updateWorldMap(world, world.model.currentMap, world.model.currentTileMap, world.tileManager.currentMapTiles, res);
|
||||
}
|
||||
|
||||
private static void updateWorldMap(
|
||||
final WorldContext world,
|
||||
final PredefinedMap map,
|
||||
final LayeredTileMap mapTiles,
|
||||
final TileCollection cachedTiles,
|
||||
final Resources res) {
|
||||
final String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(map.name);
|
||||
if (worldMapSegmentName == null) return;
|
||||
|
||||
if (!shouldUpdateWorldMap(map, worldMapSegmentName)) return;
|
||||
|
||||
|
||||
if (!shouldUpdateWorldMap(map, worldMapSegmentName, world.maps.worldMapRequiresUpdate)) return;
|
||||
|
||||
(new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... arg0) {
|
||||
@@ -53,24 +57,27 @@ public final class WorldMapController {
|
||||
try {
|
||||
updateCachedBitmap(map, renderer);
|
||||
updateWorldMapSegment(res, world, worldMapSegmentName);
|
||||
world.maps.worldMapRequiresUpdate = false;
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("WorldMapController: Updated worldmap segment " + worldMapSegmentName + " for map " + map.name);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
L.log("Error creating worldmap file for map " + map.name + " : " + e.toString());
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
|
||||
private static boolean shouldUpdateWorldMap(PredefinedMap map, String worldMapSegmentName) {
|
||||
private static boolean shouldUpdateWorldMap(PredefinedMap map, String worldMapSegmentName, boolean forceUpdate) {
|
||||
if (forceUpdate) return true;
|
||||
if (!map.visited) return true;
|
||||
File file = getFileForMap(map);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
if (map.lastVisitVersion < AndorsTrailApplication.CURRENT_VERSION) return true;
|
||||
|
||||
file = getCombinedWorldMapFile(worldMapSegmentName);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -78,9 +85,7 @@ public final class WorldMapController {
|
||||
ensureWorldmapDirectoryExists();
|
||||
|
||||
File file = getFileForMap(map);
|
||||
if (file.exists()) {
|
||||
if (map.lastVisitVersion == AndorsTrailApplication.CURRENT_VERSION) return;
|
||||
}
|
||||
if (file.exists()) return;
|
||||
|
||||
Bitmap image = renderer.drawMap();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
@@ -88,6 +93,17 @@ public final class WorldMapController {
|
||||
fos.flush();
|
||||
fos.close();
|
||||
image.recycle();
|
||||
L.log("WorldMapController: Wrote " + file.getAbsolutePath());
|
||||
|
||||
// Before we had the hash as part of the filename, the png files were just named [mapname].png
|
||||
// let's just remove those old files since the new hash-based filenames contain the same data.
|
||||
if (map.lastSeenLayoutHash.length() > 0) {
|
||||
File oldFile = getFileForMap(map.name);
|
||||
if (!oldFile.getName().equalsIgnoreCase(file.getName())) {
|
||||
oldFile.delete();
|
||||
L.log("WorldMapController: Deleted " + oldFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MapRenderer {
|
||||
@@ -114,15 +130,15 @@ public final class WorldMapController {
|
||||
canvas.scale(scale, scale);
|
||||
|
||||
synchronized (cachedTiles) {
|
||||
drawMapLayer(canvas, mapTiles.layers[LayeredTileMap.LAYER_GROUND]);
|
||||
tryDrawMapLayer(canvas, LayeredTileMap.LAYER_OBJECTS);
|
||||
tryDrawMapLayer(canvas, LayeredTileMap.LAYER_ABOVE);
|
||||
drawMapLayer(canvas, mapTiles.currentLayout.layerGround);
|
||||
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerObjects);
|
||||
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerAbove);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private void tryDrawMapLayer(Canvas canvas, final int layerIndex) {
|
||||
if (mapTiles.layers.length > layerIndex) drawMapLayer(canvas, mapTiles.layers[layerIndex]);
|
||||
|
||||
private void tryDrawMapLayer(Canvas canvas, final MapLayer layer) {
|
||||
if (layer != null) drawMapLayer(canvas, layer);
|
||||
}
|
||||
|
||||
private void drawMapLayer(Canvas canvas, final MapLayer layer) {
|
||||
@@ -144,11 +160,14 @@ public final class WorldMapController {
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
dir = new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
|
||||
|
||||
File noMediaFile = new File(dir, ".nomedia");
|
||||
if (!noMediaFile.exists()) noMediaFile.createNewFile();
|
||||
}
|
||||
private static File getFileForMap(PredefinedMap map) { return getFileForMap(map.name); }
|
||||
private static File getFileForMap(PredefinedMap map) {
|
||||
if (map.lastSeenLayoutHash.length() <= 0) return getFileForMap(map.name);
|
||||
else return getFileForMap(map.name + "." + map.lastSeenLayoutHash);
|
||||
}
|
||||
private static File getFileForMap(String mapName) {
|
||||
return new File(getWorldmapDirectory(), mapName + ".png");
|
||||
}
|
||||
@@ -161,19 +180,19 @@ public final class WorldMapController {
|
||||
return new File(getWorldmapDirectory(), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
|
||||
}
|
||||
|
||||
private static boolean shouldDisplayMapOnWorldmap(String mapName) {
|
||||
File f = WorldMapController.getFileForMap(mapName);
|
||||
return f.exists();
|
||||
}
|
||||
private static String getWorldMapSegmentAsHtml(Resources res, WorldContext world, String segmentName) {
|
||||
WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName);
|
||||
|
||||
Collection<String> displayedMapNames = new HashSet<String>();
|
||||
Map<String, File> displayedMapFilenamesPerMapName = new HashMap<String, File>(segment.maps.size());
|
||||
Coord offsetWorldmapTo = new Coord(999999, 999999);
|
||||
for (WorldMapSegmentMap map : segment.maps.values()) {
|
||||
if (!shouldDisplayMapOnWorldmap(map.mapName)) continue;
|
||||
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
|
||||
if (predefinedMap == null) continue;
|
||||
if (!predefinedMap.visited) continue;
|
||||
File f = WorldMapController.getFileForMap(predefinedMap);
|
||||
if (!f.exists()) continue;
|
||||
displayedMapFilenamesPerMapName.put(map.mapName, f);
|
||||
|
||||
displayedMapNames.add(map.mapName);
|
||||
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
|
||||
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
|
||||
}
|
||||
@@ -182,8 +201,8 @@ public final class WorldMapController {
|
||||
|
||||
StringBuilder mapsAsHtml = new StringBuilder(1000);
|
||||
for (WorldMapSegmentMap segmentMap : segment.maps.values()) {
|
||||
File f = WorldMapController.getFileForMap(segmentMap.mapName);
|
||||
if (!f.exists()) continue;
|
||||
File f = displayedMapFilenamesPerMapName.get(segmentMap.mapName);
|
||||
if (f == null) continue;
|
||||
|
||||
Size size = getMapSize(segmentMap, world);
|
||||
mapsAsHtml
|
||||
@@ -212,7 +231,7 @@ public final class WorldMapController {
|
||||
|
||||
StringBuilder namedAreasAsHtml = new StringBuilder(500);
|
||||
for (NamedWorldMapArea area : segment.namedAreas.values()) {
|
||||
CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapNames);
|
||||
CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapFilenamesPerMapName.keySet());
|
||||
if (r == null) continue;
|
||||
namedAreasAsHtml
|
||||
.append("<div class=\"namedarea ")
|
||||
@@ -244,7 +263,7 @@ public final class WorldMapController {
|
||||
return world.maps.findPredefinedMap(map.mapName).size;
|
||||
}
|
||||
|
||||
private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, Collection<String> displayedMapNames) {
|
||||
private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, Set<String> displayedMapNames) {
|
||||
Coord topLeft = null;
|
||||
Coord bottomRight = null;
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.gpl.rpg.AndorsTrail.controller.listeners;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.util.ListOfListeners;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
|
||||
public final class LootBagListeners extends ListOfListeners<LootBagListener> implements LootBagListener {
|
||||
|
||||
private final Function2<LootBagListener, PredefinedMap, Coord> onLootBagCreated = new Function2<LootBagListener, PredefinedMap, Coord>() {
|
||||
@Override public void call(LootBagListener listener, PredefinedMap map, Coord p) { listener.onLootBagCreated(map, p); }
|
||||
};
|
||||
|
||||
private final Function2<LootBagListener, PredefinedMap, Coord> onLootBagRemoved = new Function2<LootBagListener, PredefinedMap, Coord>() {
|
||||
@Override public void call(LootBagListener listener, PredefinedMap map, Coord p) { listener.onLootBagRemoved(map, p); }
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onLootBagCreated(PredefinedMap map, Coord p) {
|
||||
callAllListeners(this.onLootBagCreated, map, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLootBagRemoved(PredefinedMap map, Coord p) {
|
||||
callAllListeners(this.onLootBagRemoved, map, p);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.gpl.rpg.AndorsTrail.controller.listeners;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
|
||||
public interface LootBagListener {
|
||||
public interface MapLayoutListener {
|
||||
void onLootBagCreated(PredefinedMap map, Coord p);
|
||||
void onLootBagRemoved(PredefinedMap map, Coord p);
|
||||
void onMapTilesChanged(PredefinedMap map, LayeredTileMap tileMap);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.gpl.rpg.AndorsTrail.controller.listeners;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
|
||||
import com.gpl.rpg.AndorsTrail.util.ListOfListeners;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
|
||||
public final class MapLayoutListeners extends ListOfListeners<MapLayoutListener> implements MapLayoutListener {
|
||||
|
||||
private final Function2<MapLayoutListener, PredefinedMap, Coord> onLootBagCreated = new Function2<MapLayoutListener, PredefinedMap, Coord>() {
|
||||
@Override public void call(MapLayoutListener listener, PredefinedMap map, Coord p) { listener.onLootBagCreated(map, p); }
|
||||
};
|
||||
|
||||
private final Function2<MapLayoutListener, PredefinedMap, Coord> onLootBagRemoved = new Function2<MapLayoutListener, PredefinedMap, Coord>() {
|
||||
@Override public void call(MapLayoutListener listener, PredefinedMap map, Coord p) { listener.onLootBagRemoved(map, p); }
|
||||
};
|
||||
|
||||
private final Function2<MapLayoutListener, PredefinedMap, LayeredTileMap> onMapTilesChanged = new Function2<MapLayoutListener, PredefinedMap, LayeredTileMap>() {
|
||||
@Override public void call(MapLayoutListener listener, PredefinedMap map, LayeredTileMap tileMap) { listener.onMapTilesChanged(map, tileMap); }
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onLootBagCreated(PredefinedMap map, Coord p) {
|
||||
callAllListeners(this.onLootBagCreated, map, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLootBagRemoved(PredefinedMap map, Coord p) {
|
||||
callAllListeners(this.onLootBagRemoved, map, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapTilesChanged(PredefinedMap map, LayeredTileMap tileMap) {
|
||||
callAllListeners(this.onMapTilesChanged, map, tileMap);
|
||||
}
|
||||
}
|
||||
@@ -11,46 +11,38 @@ import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class LayeredTileMap {
|
||||
public static final int LAYER_GROUND = 0;
|
||||
public static final int LAYER_OBJECTS = 1;
|
||||
public static final int LAYER_ABOVE = 2;
|
||||
|
||||
private static final ColorFilter colorFilterBlack20 = createGrayScaleColorFilter(0.2f);
|
||||
private static final ColorFilter colorFilterBlack40 = createGrayScaleColorFilter(0.4f);
|
||||
private static final ColorFilter colorFilterBlack60 = createGrayScaleColorFilter(0.6f);
|
||||
private static final ColorFilter colorFilterBlack80 = createGrayScaleColorFilter(0.8f);
|
||||
|
||||
private final Size size;
|
||||
public final MapLayer[] layers;
|
||||
public final Collection<Integer> usedTileIDs;
|
||||
private final boolean[][] isWalkable;
|
||||
public final MapSection currentLayout;
|
||||
private String currentLayoutHash;
|
||||
public final ReplaceableMapSection[] replacements;
|
||||
public final String colorFilter;
|
||||
|
||||
public final Collection<Integer> usedTileIDs;
|
||||
public LayeredTileMap(
|
||||
Size size,
|
||||
MapLayer[] layers,
|
||||
boolean[][] isWalkable,
|
||||
Collection<Integer> usedTileIDs,
|
||||
String colorFilter) {
|
||||
assert(size.width > 0);
|
||||
assert(size.height > 0);
|
||||
assert(layers.length == 3);
|
||||
assert(isWalkable.length == size.width);
|
||||
assert(isWalkable[0].length == size.height);
|
||||
MapSection layout,
|
||||
ReplaceableMapSection[] replacements,
|
||||
String colorFilter,
|
||||
Collection<Integer> usedTileIDs) {
|
||||
this.size = size;
|
||||
this.layers = layers;
|
||||
this.usedTileIDs = usedTileIDs;
|
||||
this.isWalkable = isWalkable;
|
||||
this.currentLayout = layout;
|
||||
this.replacements = replacements;
|
||||
this.colorFilter = colorFilter;
|
||||
this.usedTileIDs = usedTileIDs;
|
||||
this.currentLayoutHash = currentLayout.calculateHash();
|
||||
}
|
||||
|
||||
public final boolean isWalkable(final Coord p) {
|
||||
if (isOutside(p.x, p.y)) return false;
|
||||
return isWalkable[p.x][p.y];
|
||||
return currentLayout.isWalkable[p.x][p.y];
|
||||
}
|
||||
public final boolean isWalkable(final int x, final int y) {
|
||||
if (isOutside(x, y)) return false;
|
||||
return isWalkable[x][y];
|
||||
return currentLayout.isWalkable[x][y];
|
||||
}
|
||||
public final boolean isWalkable(final CoordRect p) {
|
||||
for (int y = 0; y < p.size.height; ++y) {
|
||||
@@ -98,4 +90,13 @@ public final class LayeredTileMap {
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
}
|
||||
|
||||
public String getCurrentLayoutHash() {
|
||||
return currentLayoutHash;
|
||||
}
|
||||
|
||||
public void applyReplacement(ReplaceableMapSection replacement) {
|
||||
replacement.apply(currentLayout);
|
||||
currentLayoutHash = currentLayout.calculateHash();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.util.List;
|
||||
public final class MapCollection {
|
||||
private final HashMap<String, PredefinedMap> predefinedMaps = new HashMap<String, PredefinedMap>();
|
||||
public final HashMap<String, WorldMapSegment> worldMapSegments = new HashMap<String, WorldMapSegment>();
|
||||
public boolean worldMapRequiresUpdate = true;
|
||||
|
||||
public MapCollection() {}
|
||||
|
||||
@@ -43,6 +44,7 @@ public final class MapCollection {
|
||||
for (PredefinedMap m : getAllMaps()) {
|
||||
m.reset();
|
||||
}
|
||||
worldMapRequiresUpdate = true;
|
||||
}
|
||||
|
||||
public String getWorldMapSegmentNameForMap(String mapName) {
|
||||
|
||||
@@ -4,27 +4,12 @@ import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class MapLayer {
|
||||
private final Size size;
|
||||
public final int[][] tiles;
|
||||
|
||||
public MapLayer(Size size) {
|
||||
this.size = size;
|
||||
tiles = new int[size.width][size.height];
|
||||
}
|
||||
public void setTile(int type, int x, int y) {
|
||||
tiles[x][y] = type;
|
||||
}
|
||||
public void setTile(int type, Coord p) {
|
||||
setTile(type, p.x, p.y);
|
||||
}
|
||||
public final boolean isOutside(int x, int y) {
|
||||
if (x < 0) return true;
|
||||
if (y < 0) return true;
|
||||
if (x >= size.width) return true;
|
||||
if (y >= size.height) return true;
|
||||
return false;
|
||||
}
|
||||
public final boolean isOutside(Coord p) {
|
||||
return isOutside(p.x, p.y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.map;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.util.ByteUtils;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
|
||||
public final class MapSection {
|
||||
public final MapLayer layerGround;
|
||||
public final MapLayer layerObjects;
|
||||
public final MapLayer layerAbove;
|
||||
public final boolean[][] isWalkable;
|
||||
private final byte[] layoutHash;
|
||||
|
||||
public MapSection(
|
||||
MapLayer layerGround,
|
||||
MapLayer layerObjects,
|
||||
MapLayer layerAbove,
|
||||
boolean[][] isWalkable,
|
||||
byte[] layoutHash) {
|
||||
this.layerGround = layerGround;
|
||||
this.layerObjects = layerObjects;
|
||||
this.layerAbove = layerAbove;
|
||||
this.isWalkable = isWalkable;
|
||||
this.layoutHash = layoutHash;
|
||||
}
|
||||
|
||||
public void replaceLayerContentsWith(final MapSection replaceLayersWith, final CoordRect replacementArea) {
|
||||
replaceTileLayerSection(layerGround, replaceLayersWith.layerGround, replacementArea);
|
||||
replaceTileLayerSection(layerObjects, replaceLayersWith.layerObjects, replacementArea);
|
||||
replaceTileLayerSection(layerAbove, replaceLayersWith.layerAbove, replacementArea);
|
||||
if (replaceLayersWith.isWalkable != null) {
|
||||
final int dy = replacementArea.topLeft.y;
|
||||
final int height = replacementArea.size.height;
|
||||
for (int sx = 0, dx = replacementArea.topLeft.x; sx < replacementArea.size.width; ++sx, ++dx) {
|
||||
System.arraycopy(replaceLayersWith.isWalkable[sx], 0, isWalkable[dx], dy, height);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < layoutHash.length; ++i) {
|
||||
layoutHash[i] ^= replaceLayersWith.layoutHash[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static void replaceTileLayerSection(MapLayer dest, MapLayer src, CoordRect area) {
|
||||
if (src == null) return;
|
||||
final int dy = area.topLeft.y;
|
||||
final int height = area.size.height;
|
||||
for (int sx = 0, dx = area.topLeft.x; sx < area.size.width; ++sx, ++dx) {
|
||||
System.arraycopy(src.tiles[sx], 0, dest.tiles[dx], dy, height);
|
||||
}
|
||||
}
|
||||
|
||||
public String calculateHash() {
|
||||
return ByteUtils.toHexString(layoutHash, 4);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public final class PredefinedMap {
|
||||
public final ArrayList<Loot> groundBags = new ArrayList<Loot>();
|
||||
public boolean visited = false;
|
||||
public long lastVisitTime = VISIT_RESET;
|
||||
public int lastVisitVersion = 0;
|
||||
public String lastSeenLayoutHash = "";
|
||||
private final boolean isOutdoors;
|
||||
|
||||
public final ArrayList<BloodSplatter> splatters = new ArrayList<BloodSplatter>();
|
||||
@@ -136,7 +136,7 @@ public final class PredefinedMap {
|
||||
}
|
||||
groundBags.clear();
|
||||
visited = false;
|
||||
lastVisitVersion = 0;
|
||||
lastSeenLayoutHash = "";
|
||||
}
|
||||
|
||||
public boolean isRecentlyVisited() {
|
||||
@@ -145,7 +145,6 @@ public final class PredefinedMap {
|
||||
}
|
||||
public void updateLastVisitTime() {
|
||||
lastVisitTime = System.currentTimeMillis();
|
||||
lastVisitVersion = AndorsTrailApplication.CURRENT_VERSION;
|
||||
}
|
||||
public void resetTemporaryData() {
|
||||
for(MonsterSpawnArea a : spawnAreas) {
|
||||
@@ -213,10 +212,13 @@ public final class PredefinedMap {
|
||||
lastVisitTime = src.readLong();
|
||||
|
||||
if (visited) {
|
||||
if (fileversion <= 30) lastVisitVersion = 30;
|
||||
else lastVisitVersion = src.readInt();
|
||||
if (fileversion > 30 && fileversion < 36) {
|
||||
/*int lastVisitVersion = */src.readInt();
|
||||
}
|
||||
if (fileversion < 36) lastSeenLayoutHash = "";
|
||||
else lastSeenLayoutHash = src.readUTF();
|
||||
}
|
||||
|
||||
|
||||
for(int i = loadedSpawnAreas; i < spawnAreas.length; ++i) {
|
||||
MonsterSpawnArea area = this.spawnAreas[i];
|
||||
if (area.isUnique && visited) controllers.monsterSpawnController.spawnAllInArea(this, null, area, true);
|
||||
@@ -235,6 +237,8 @@ public final class PredefinedMap {
|
||||
}
|
||||
dest.writeBoolean(visited);
|
||||
dest.writeLong(lastVisitTime);
|
||||
if (visited) dest.writeInt(lastVisitVersion);
|
||||
if (visited) {
|
||||
dest.writeUTF(lastSeenLayoutHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.map;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
|
||||
public final class ReplaceableMapSection {
|
||||
public boolean isApplied = false;
|
||||
public final CoordRect replacementArea;
|
||||
public final MapSection replaceLayersWith;
|
||||
public final QuestProgress requireQuestStage;
|
||||
|
||||
public ReplaceableMapSection(
|
||||
CoordRect replacementArea,
|
||||
MapSection replaceLayersWith,
|
||||
QuestProgress requireQuestStage) {
|
||||
this.replacementArea = replacementArea;
|
||||
this.replaceLayersWith = replaceLayersWith;
|
||||
this.requireQuestStage = requireQuestStage;
|
||||
}
|
||||
|
||||
public void apply(MapSection dest) {
|
||||
dest.replaceLayerContentsWith(replaceLayersWith, replacementArea);
|
||||
isApplied = true;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.map;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import com.gpl.rpg.AndorsTrail.util.Base64;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
import com.gpl.rpg.AndorsTrail.util.XmlResourceParserUtils;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.util.Base64;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
import com.gpl.rpg.AndorsTrail.util.XmlResourceParserUtils;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
|
||||
public final class TMXMapFileParser {
|
||||
public static TMXMap read(Resources r, int xmlResourceId, String name) {
|
||||
return read(r.getXml(xmlResourceId), xmlResourceId, name);
|
||||
public static TMXObjectMap readObjectMap(Resources r, int xmlResourceId, String name) {
|
||||
return readObjectMap(r.getXml(xmlResourceId), xmlResourceId, name);
|
||||
}
|
||||
|
||||
public static TMXLayerMap readLayeredTileMap(Resources r, int xmlResourceId, String name) {
|
||||
public static TMXLayerMap readLayerMap(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();
|
||||
private static TMXObjectMap readObjectMap(XmlResourceParser xrp, int xmlResourceId, String name) {
|
||||
final TMXObjectMap map = new TMXObjectMap();
|
||||
map.xmlResourceId = xmlResourceId;
|
||||
try {
|
||||
// Map format: http://sourceforge.net/apps/mediawiki/tiled/index.php?title=Examining_the_map_format
|
||||
@@ -35,7 +35,6 @@ public final class TMXMapFileParser {
|
||||
String s = xrp.getName();
|
||||
if (s.equals("map")) {
|
||||
map.name = name;
|
||||
map.orientation = xrp.getAttributeValue(null, "orientation");
|
||||
map.width = xrp.getAttributeIntValue(null, "width", -1);
|
||||
map.height = xrp.getAttributeIntValue(null, "height", -1);
|
||||
map.tilewidth = xrp.getAttributeIntValue(null, "tilewidth", -1);
|
||||
@@ -72,8 +71,11 @@ public final class TMXMapFileParser {
|
||||
if (eventType == XmlResourceParser.START_TAG) {
|
||||
String s = xrp.getName();
|
||||
if (s.equals("map")) {
|
||||
map.name = name;
|
||||
map.width = xrp.getAttributeIntValue(null, "width", -1);
|
||||
map.height = xrp.getAttributeIntValue(null, "height", -1);
|
||||
map.tilewidth = xrp.getAttributeIntValue(null, "tilewidth", -1);
|
||||
map.tileheight = xrp.getAttributeIntValue(null, "tileheight", -1);
|
||||
XmlResourceParserUtils.readCurrentTagUntilEnd(xrp, new XmlResourceParserUtils.TagHandler() {
|
||||
public void handleTag(XmlResourceParser xrp, String tagName) throws XmlPullParserException, IOException {
|
||||
if (tagName.equals("tileset")) {
|
||||
@@ -82,6 +84,8 @@ public final class TMXMapFileParser {
|
||||
layers.add(readTMXMapLayer(xrp));
|
||||
} else if (tagName.equals("property")) {
|
||||
map.properties.add(readTMXProperty(xrp));
|
||||
} else if (tagName.equals("objectgroup")) {
|
||||
map.objectGroups.add(readTMXObjectGroup(xrp));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -196,11 +200,17 @@ public final class TMXMapFileParser {
|
||||
for(int y = 0; y < layer.height; ++y) {
|
||||
for(int x = 0; x < layer.width; ++x, i += 4) {
|
||||
int gid = readIntLittleEndian(buffer, i);
|
||||
//if (gid != 0) L.log(getHexString(buffer, i) + " -> " + gid);
|
||||
layer.gids[x][y] = gid;
|
||||
//L.log("(" + x + "," + y + ") : " + layer.gids[x][y]);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("MD5");
|
||||
digest.update(buffer);
|
||||
layer.layoutHash = digest.digest();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IOException("Failed to create layout hash for map layer " + layer.name);
|
||||
}
|
||||
}
|
||||
|
||||
private static TMXProperty readTMXProperty(XmlResourceParser xrp) {
|
||||
@@ -241,19 +251,21 @@ public final class TMXMapFileParser {
|
||||
(buffer[offset + 3] << 24) & 0xff000000;
|
||||
}
|
||||
|
||||
public static final class TMXMap extends TMXLayerMap {
|
||||
public static final class TMXObjectMap extends TMXMap {
|
||||
public int xmlResourceId;
|
||||
public String name;
|
||||
public String orientation;
|
||||
public int tilewidth;
|
||||
public int tileheight;
|
||||
public final ArrayList<TMXObjectGroup> objectGroups = new ArrayList<TMXObjectGroup>();
|
||||
}
|
||||
public static class TMXLayerMap {
|
||||
public int width;
|
||||
public int height;
|
||||
public static final class TMXLayerMap extends TMXMap {
|
||||
public TMXTileSet[] tileSets;
|
||||
public TMXLayer[] layers;
|
||||
public final ArrayList<TMXObjectGroup> objectGroups = new ArrayList<TMXObjectGroup>();
|
||||
}
|
||||
public static class TMXMap {
|
||||
public String name;
|
||||
public int width;
|
||||
public int height;
|
||||
public int tilewidth;
|
||||
public int tileheight;
|
||||
public final ArrayList<TMXProperty> properties = new ArrayList<TMXProperty>();
|
||||
}
|
||||
public static final class TMXTileSet {
|
||||
@@ -269,6 +281,7 @@ public final class TMXMapFileParser {
|
||||
public int width;
|
||||
public int height;
|
||||
public int[][] gids;
|
||||
public byte[] layoutHash;
|
||||
}
|
||||
public static final class TMXObjectGroup {
|
||||
public String name;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.map;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
|
||||
@@ -12,12 +12,12 @@ 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.TMXObjectMap;
|
||||
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.tiles.TileCache;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
@@ -28,25 +28,24 @@ import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
import android.content.res.Resources;
|
||||
|
||||
public final class TMXMapTranslator {
|
||||
private final ArrayList<TMXMap> maps = new ArrayList<TMXMap>();
|
||||
private final ArrayList<TMXObjectMap> maps = new ArrayList<TMXObjectMap>();
|
||||
|
||||
public void read(Resources r, int xmlResourceId, String name) {
|
||||
maps.add(TMXMapFileParser.read(r, xmlResourceId, name));
|
||||
maps.add(TMXMapFileParser.readObjectMap(r, xmlResourceId, name));
|
||||
}
|
||||
|
||||
public static LayeredTileMap readLayeredTileMap(Resources res, TileCache tileCache, PredefinedMap map) {
|
||||
TMXLayerMap resultMap = TMXMapFileParser.readLayeredTileMap(res, map.xmlResourceId, map.name);
|
||||
return transformMap(resultMap, tileCache, map.name);
|
||||
TMXLayerMap resultMap = TMXMapFileParser.readLayerMap(res, map.xmlResourceId, map.name);
|
||||
return transformMap(resultMap, tileCache);
|
||||
}
|
||||
|
||||
public ArrayList<PredefinedMap> transformMaps(MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
|
||||
return transformMaps(maps, monsterTypes, dropLists);
|
||||
}
|
||||
public ArrayList<PredefinedMap> transformMaps(Collection<TMXMap> maps, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
|
||||
public ArrayList<PredefinedMap> transformMaps(Collection<TMXObjectMap> maps, MonsterTypeCollection monsterTypes, DropListCollection dropLists) {
|
||||
ArrayList<PredefinedMap> result = new ArrayList<PredefinedMap>();
|
||||
|
||||
Tile tile = new Tile();
|
||||
for (TMXMap m : maps) {
|
||||
for (TMXObjectMap m : maps) {
|
||||
assert(m.name != null);
|
||||
assert(m.name.length() > 0);
|
||||
assert(m.width > 0);
|
||||
@@ -64,13 +63,7 @@ public final class TMXMapTranslator {
|
||||
|
||||
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));
|
||||
final CoordRect position = getTMXObjectPosition(object, m);
|
||||
|
||||
if (object.type == null) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA)
|
||||
@@ -148,6 +141,8 @@ public final class TMXMapTranslator {
|
||||
DropList dropList = dropLists.getDropList(object.name);
|
||||
if (dropList == null) continue;
|
||||
mapObjects.add(MapObject.createNewContainerArea(position, dropList));
|
||||
} else if (object.type.equals("replace")) {
|
||||
// Do nothing. Will be handled when reading map layers instead.
|
||||
} else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
L.log("OPTIMIZE: Map " + m.name + ", has unrecognized object type \"" + object.type + "\" for name \"" + object.name + "\".");
|
||||
}
|
||||
@@ -163,66 +158,178 @@ public final class TMXMapTranslator {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static LayeredTileMap transformMap(TMXLayerMap map, TileCache tileCache, String mapName) {
|
||||
private static CoordRect getTMXObjectPosition(TMXObject object, TMXMap m) {
|
||||
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);
|
||||
return new CoordRect(topLeft, new Size(width, height));
|
||||
}
|
||||
|
||||
private static final String LAYERNAME_GROUND = "ground";
|
||||
private static final String LAYERNAME_OBJECTS = "objects";
|
||||
private static final String LAYERNAME_ABOVE = "above";
|
||||
private static final String LAYERNAME_WALKABLE = "walkable";
|
||||
private static final SetOfLayerNames defaultLayerNames = new SetOfLayerNames(LAYERNAME_GROUND, LAYERNAME_OBJECTS, LAYERNAME_ABOVE, LAYERNAME_WALKABLE);
|
||||
|
||||
private static LayeredTileMap transformMap(TMXLayerMap map, TileCache tileCache) {
|
||||
final Size mapSize = new Size(map.width, map.height);
|
||||
final MapLayer[] layers = new MapLayer[] {
|
||||
new MapLayer(mapSize)
|
||||
,new MapLayer(mapSize)
|
||||
,new MapLayer(mapSize)
|
||||
};
|
||||
boolean[][] isWalkable = new boolean[map.width][map.height];
|
||||
for (int y = 0; y < map.height; ++y) {
|
||||
for (int x = 0; x < map.width; ++x) {
|
||||
isWalkable[x][y] = true;
|
||||
}
|
||||
}
|
||||
Tile tile = new Tile();
|
||||
String colorFilter = null;
|
||||
for (TMXProperty prop : map.properties) {
|
||||
if (prop.name.equalsIgnoreCase("colorfilter")) colorFilter = prop.value;
|
||||
}
|
||||
HashSet<Integer> usedTileIDs = new HashSet<Integer>();
|
||||
HashMap<String, TMXLayer> layersPerLayerName = new HashMap<String, TMXLayer>();
|
||||
for (TMXLayer layer : map.layers) {
|
||||
int ixMapLayer = 0;
|
||||
String layerName = layer.name;
|
||||
assert(layerName != null);
|
||||
assert(layerName.length() > 0);
|
||||
layerName = layerName.toLowerCase();
|
||||
boolean isWalkableLayer = false;
|
||||
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 if (layerName.startsWith("walk")) {
|
||||
isWalkableLayer = true;
|
||||
} else {
|
||||
continue;
|
||||
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
if (layersPerLayerName.containsKey(layerName)) {
|
||||
L.log("WARNING: Map \"" + map.name + "\" contains multiple layers with name \"" + layerName + "\".");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
layersPerLayerName.put(layerName, layer);
|
||||
}
|
||||
|
||||
if (isWalkableLayer) {
|
||||
isWalkable[x][y] = false;
|
||||
} else {
|
||||
int tileID = tileCache.getTileID(tile.tilesetName, tile.localId);
|
||||
layers[ixMapLayer].tiles[x][y] = tileID;
|
||||
usedTileIDs.add(tileID);
|
||||
MapSection defaultLayout = transformMapSection(map,
|
||||
tileCache,
|
||||
new CoordRect(new Coord(0,0), mapSize),
|
||||
layersPerLayerName,
|
||||
usedTileIDs,
|
||||
defaultLayerNames);
|
||||
|
||||
ArrayList<ReplaceableMapSection> replaceableSections = new ArrayList<ReplaceableMapSection>();
|
||||
for (TMXObjectGroup objectGroup : map.objectGroups) {
|
||||
for(TMXObject obj : objectGroup.objects) {
|
||||
if ("replace".equals(obj.type)) {
|
||||
final CoordRect position = getTMXObjectPosition(obj, map);
|
||||
SetOfLayerNames layerNames = new SetOfLayerNames();
|
||||
for (TMXProperty prop : obj.properties) {
|
||||
if (prop.name.equalsIgnoreCase(LAYERNAME_GROUND)) layerNames.groundLayerName = prop.value;
|
||||
else if (prop.name.equalsIgnoreCase(LAYERNAME_OBJECTS)) layerNames.objectsLayerName = prop.value;
|
||||
else if (prop.name.equalsIgnoreCase(LAYERNAME_ABOVE)) layerNames.aboveLayersName = prop.value;
|
||||
else if (prop.name.equalsIgnoreCase(LAYERNAME_WALKABLE)) layerNames.walkableLayersName = prop.value;
|
||||
else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
L.log("OPTIMIZE: Map " + map.name + " contains replace area with unknown property \"" + prop.name + "\".");
|
||||
}
|
||||
}
|
||||
MapSection replacementSection = transformMapSection(map, tileCache, position, layersPerLayerName, usedTileIDs, layerNames);
|
||||
QuestProgress requireQuestStage = QuestProgress.parseQuestProgress(obj.name);
|
||||
if (requireQuestStage == null) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
L.log("OPTIMIZE: Map " + map.name + " contains replace area that cannot be parsed as a quest stage.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
replaceableSections.add(new ReplaceableMapSection(position, replacementSection, requireQuestStage));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new LayeredTileMap(mapSize, layers, isWalkable, usedTileIDs, colorFilter);
|
||||
|
||||
ReplaceableMapSection[] replaceableSections_ = null;
|
||||
if (!replaceableSections.isEmpty()) {
|
||||
replaceableSections_ = replaceableSections.toArray(new ReplaceableMapSection[replaceableSections.size()]);
|
||||
}
|
||||
return new LayeredTileMap(mapSize, defaultLayout, replaceableSections_, colorFilter, usedTileIDs);
|
||||
}
|
||||
|
||||
|
||||
private static MapSection transformMapSection(
|
||||
TMXLayerMap srcMap,
|
||||
TileCache tileCache,
|
||||
CoordRect area,
|
||||
HashMap<String, TMXLayer> layersPerLayerName,
|
||||
HashSet<Integer> usedTileIDs,
|
||||
SetOfLayerNames layerNames
|
||||
) {
|
||||
final MapLayer layerGround = transformMapLayer(layersPerLayerName, layerNames.groundLayerName, srcMap, tileCache, area, usedTileIDs);
|
||||
final MapLayer layerObjects = transformMapLayer(layersPerLayerName, layerNames.objectsLayerName, srcMap, tileCache, area, usedTileIDs);
|
||||
final MapLayer layerAbove = transformMapLayer(layersPerLayerName, layerNames.aboveLayersName, srcMap, tileCache, area, usedTileIDs);
|
||||
boolean[][] isWalkable = transformWalkableMapLayer(findLayer(layersPerLayerName, layerNames.walkableLayersName, srcMap.name), area);
|
||||
byte[] layoutHash = calculateLayoutHash(srcMap, layersPerLayerName, layerNames);
|
||||
return new MapSection(layerGround, layerObjects, layerAbove, isWalkable, layoutHash);
|
||||
}
|
||||
|
||||
private static TMXLayer findLayer(HashMap<String, TMXLayer> layersPerLayerName, String layerName, String mapName) {
|
||||
if (layerName == null) return null;
|
||||
if (layerName.length() == 0) return null;
|
||||
TMXLayer result = layersPerLayerName.get(layerName);
|
||||
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
if (result == null) {
|
||||
L.log("WARNING: Cannot find maplayer \"" + layerName + "\" requested by map \"" + mapName + "\".");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static MapLayer transformMapLayer(
|
||||
HashMap<String, TMXLayer> layersPerLayerName,
|
||||
String layerName,
|
||||
TMXLayerMap srcMap,
|
||||
TileCache tileCache,
|
||||
CoordRect area,
|
||||
HashSet<Integer> usedTileIDs
|
||||
) {
|
||||
TMXLayer srcLayer = findLayer(layersPerLayerName, layerName, srcMap.name);
|
||||
if (srcLayer == null) return null;
|
||||
final MapLayer result = new MapLayer(area.size);
|
||||
Tile tile = new Tile();
|
||||
for (int dy = 0, sy = area.topLeft.y; dy < area.size.height; ++dy, ++sy) {
|
||||
for (int dx = 0, sx = area.topLeft.x; dx < area.size.width; ++dx, ++sx) {
|
||||
int gid = srcLayer.gids[sx][sy];
|
||||
if (gid <= 0) continue;
|
||||
|
||||
if (!getTile(srcMap, gid, tile)) continue;
|
||||
|
||||
int tileID = tileCache.getTileID(tile.tilesetName, tile.localId);
|
||||
result.tiles[dx][dy] = tileID;
|
||||
usedTileIDs.add(tileID);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean[][] transformWalkableMapLayer(TMXLayer srcLayer, CoordRect area) {
|
||||
if (srcLayer == null) return null;
|
||||
final boolean[][] isWalkable = new boolean[area.size.width][area.size.height];
|
||||
for (int x = 0; x < area.size.width; ++x) {
|
||||
Arrays.fill(isWalkable[x], true);
|
||||
}
|
||||
for (int dy = 0, sy = area.topLeft.y; dy < area.size.height; ++dy, ++sy) {
|
||||
for (int dx = 0, sx = area.topLeft.x; dx < area.size.width; ++dx, ++sx) {
|
||||
int gid = srcLayer.gids[sx][sy];
|
||||
if (gid > 0) {
|
||||
isWalkable[dx][dy] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isWalkable;
|
||||
}
|
||||
|
||||
private static byte[] calculateLayoutHash(TMXLayerMap map, HashMap<String, TMXLayer> layersPerLayerName, SetOfLayerNames layerNames) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("MD5");
|
||||
digestLayer(layersPerLayerName, layerNames.groundLayerName, map, digest);
|
||||
digestLayer(layersPerLayerName, layerNames.objectsLayerName, map, digest);
|
||||
digestLayer(layersPerLayerName, layerNames.aboveLayersName, map, digest);
|
||||
return digest.digest();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
L.log("ERROR: Failed to create layout hash for map " + map.name + " : " + e.toString());
|
||||
}
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
private static void digestLayer(HashMap<String, TMXLayer> layersPerLayerName, String layerName, TMXLayerMap map, MessageDigest digest) {
|
||||
TMXLayer srcLayer = findLayer(layersPerLayerName, layerName, map.name);
|
||||
if (srcLayer == null) return;
|
||||
if (srcLayer.layoutHash == null) return;
|
||||
digest.update(srcLayer.layoutHash);
|
||||
}
|
||||
|
||||
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];
|
||||
@@ -232,7 +339,7 @@ public final class TMXMapTranslator {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
L.log("WARNING: Cannot find tile for gid " + gid); //(" + x + ", " + y + "), ")
|
||||
L.log("WARNING: Cannot find tile for gid " + gid);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -240,73 +347,23 @@ public final class TMXMapTranslator {
|
||||
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>
|
||||
|
||||
*/
|
||||
private static final class SetOfLayerNames {
|
||||
public String groundLayerName;
|
||||
public String objectsLayerName;
|
||||
public String aboveLayersName;
|
||||
public String walkableLayersName;
|
||||
public SetOfLayerNames() {
|
||||
this.groundLayerName = null;
|
||||
this.objectsLayerName = null;
|
||||
this.aboveLayersName = null;
|
||||
this.walkableLayersName = null;
|
||||
}
|
||||
public SetOfLayerNames(String groundLayerName, String objectsLayerName, String aboveLayersName, String walkableLayersName) {
|
||||
this.groundLayerName = groundLayerName;
|
||||
this.objectsLayerName = objectsLayerName;
|
||||
this.aboveLayersName = aboveLayersName;
|
||||
this.walkableLayersName = walkableLayersName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ByteUtils.java
Normal file
16
AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ByteUtils.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.gpl.rpg.AndorsTrail.util;
|
||||
|
||||
public final class ByteUtils {
|
||||
public static String toHexString(byte[] bytes) { return toHexString(bytes, bytes.length); }
|
||||
public static String toHexString(byte[] bytes, int numBytes) {
|
||||
if (bytes == null) return "";
|
||||
if (bytes.length == 0) return "";
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (int i = 0; i < Math.min(numBytes, bytes.length); i++) {
|
||||
String h = Integer.toHexString(0xFF & bytes[i]);
|
||||
if (h.length() < 2) result.append('0');
|
||||
result.append(h);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public final class MainView extends SurfaceView
|
||||
CombatSelectionListener,
|
||||
MonsterSpawnListener,
|
||||
MonsterMovementListener,
|
||||
LootBagListener,
|
||||
MapLayoutListener,
|
||||
VisualEffectFrameListener,
|
||||
GameRoundListener {
|
||||
|
||||
@@ -276,8 +276,8 @@ public final class MainView extends SurfaceView
|
||||
|
||||
private void doDrawRect(Canvas canvas, CoordRect area) {
|
||||
|
||||
drawMapLayer(canvas, area, currentTileMap.layers[LayeredTileMap.LAYER_GROUND]);
|
||||
tryDrawMapLayer(canvas, area, LayeredTileMap.LAYER_OBJECTS);
|
||||
drawMapLayer(canvas, area, currentTileMap.currentLayout.layerGround);
|
||||
tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerObjects);
|
||||
|
||||
for (BloodSplatter splatter : currentMap.splatters) {
|
||||
drawFromMapPosition(canvas, area, splatter.position, splatter.iconID);
|
||||
@@ -296,7 +296,7 @@ public final class MainView extends SurfaceView
|
||||
}
|
||||
}
|
||||
|
||||
tryDrawMapLayer(canvas, area, LayeredTileMap.LAYER_ABOVE);
|
||||
tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerAbove);
|
||||
|
||||
if (model.uiSelections.selectedPosition != null) {
|
||||
if (model.uiSelections.selectedMonster != null) {
|
||||
@@ -307,8 +307,8 @@ public final class MainView extends SurfaceView
|
||||
}
|
||||
}
|
||||
|
||||
private void tryDrawMapLayer(Canvas canvas, final CoordRect area, final int layerIndex) {
|
||||
if (currentTileMap.layers.length > layerIndex) drawMapLayer(canvas, area, currentTileMap.layers[layerIndex]);
|
||||
private void tryDrawMapLayer(Canvas canvas, final CoordRect area, final MapLayer layer) {
|
||||
if (layer != null) drawMapLayer(canvas, area, layer);
|
||||
}
|
||||
|
||||
private void drawMapLayer(Canvas canvas, final CoordRect area, final MapLayer layer) {
|
||||
@@ -401,7 +401,7 @@ public final class MainView extends SurfaceView
|
||||
public void subscribe() {
|
||||
controllers.gameRoundController.gameRoundListeners.add(this);
|
||||
controllers.effectController.visualEffectFrameListeners.add(this);
|
||||
controllers.itemController.lootBagListeners.add(this);
|
||||
controllers.mapController.mapLayoutListeners.add(this);
|
||||
controllers.movementController.playerMovementListeners.add(this);
|
||||
controllers.combatController.combatSelectionListeners.add(this);
|
||||
controllers.monsterSpawnController.monsterSpawnListeners.add(this);
|
||||
@@ -412,7 +412,7 @@ public final class MainView extends SurfaceView
|
||||
controllers.monsterSpawnController.monsterSpawnListeners.remove(this);
|
||||
controllers.combatController.combatSelectionListeners.remove(this);
|
||||
controllers.movementController.playerMovementListeners.remove(this);
|
||||
controllers.itemController.lootBagListeners.remove(this);
|
||||
controllers.mapController.mapLayoutListeners.remove(this);
|
||||
controllers.effectController.visualEffectFrameListeners.remove(this);
|
||||
controllers.gameRoundController.gameRoundListeners.remove(this);
|
||||
}
|
||||
@@ -494,6 +494,12 @@ public final class MainView extends SurfaceView
|
||||
redrawTile(p, REDRAW_TILE_BAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapTilesChanged(PredefinedMap map, LayeredTileMap tileMap) {
|
||||
if (map != currentMap) return;
|
||||
redrawAll(REDRAW_ALL_MAP_CHANGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset) {
|
||||
redrawAreaWithEffect(animation, tileID, textYOffset);
|
||||
|
||||
Reference in New Issue
Block a user