diff --git a/AndorsTrail/res/raw/conversationlist_mikhail.json b/AndorsTrail/res/raw/conversationlist_mikhail.json index 1359ac8fe..37e7471c6 100644 --- a/AndorsTrail/res/raw/conversationlist_mikhail.json +++ b/AndorsTrail/res/raw/conversationlist_mikhail.json @@ -59,7 +59,7 @@ "id":"mikhail_start_select_default", "replies":[ { - "nextPhraseID":"mikhail_visited", + "nextPhraseID":"mikhail_default", "requires":[ { "requireType":"questProgress", @@ -114,9 +114,73 @@ "id":"mikhail_default", "message":"Anything else I can help you with?", "replies":[ + { + "text":"Do you have any more tasks for me?", + "nextPhraseID":"mikhail_all_tasks_done", + "requires":[ + { + "requireType":"questProgress", + "requireID":"mikhail_bread", + "value":100 + }, + { + "requireType":"questProgress", + "requireID":"mikhail_rats", + "value":100 + } + ] + }, + { + "text":"Do you have any more tasks for me?", + "nextPhraseID":"mikhail_bread_done", + "requires":[ + { + "requireType":"questProgress", + "requireID":"mikhail_bread", + "value":100 + }, + { + "requireType":"questProgress", + "requireID":"mikhail_rats", + "value":100, + "negate":true + } + ] + }, + { + "text":"Do you have any more tasks for me?", + "nextPhraseID":"mikhail_rats_done", + "requires":[ + { + "requireType":"questProgress", + "requireID":"mikhail_bread", + "value":100, + "negate":true + }, + { + "requireType":"questProgress", + "requireID":"mikhail_rats", + "value":100 + } + ] + }, { "text":"Do you have any tasks for me?", - "nextPhraseID":"mikhail_tasks" + "nextPhraseID":"mikhail_tasks", + "requires":[ + { + "requireType":"questProgress", + "requireID":"mikhail_bread", + "value":100, + "negate":true + }, + { + "requireType":"questProgress", + "requireID":"mikhail_rats", + "value":100, + "negate":true + } + ] }, { "text":"Is there anything else you can tell me about Andor?", @@ -142,6 +206,44 @@ } ] }, + { + "id":"mikhail_bread_done", + "message":"Thanks for getting me the bread. There are still the rats.", + "replies":[ + { + "text":"What about the rats?", + "nextPhraseID":"mikhail_rats_select" + }, + { + "text":"Never mind, let's talk about the other things.", + "nextPhraseID":"mikhail_default" + } + ] + }, + { + "id":"mikhail_rats_done", + "message":"Thanks for taking care of the rats. I'd still love some bread.", + "replies":[ + { + "text":"What about the bread?", + "nextPhraseID":"mikhail_bread_select" + }, + { + "text":"Never mind, let's talk about the other things.", + "nextPhraseID":"mikhail_default" + } + ] + }, + { + "id":"mikhail_all_tasks_done", + "message":"Not for now. Thanks for taking care of the bread and rats.", + "replies":[ + { + "text":"Never mind, let's talk about the other things.", + "nextPhraseID":"mikhail_default" + } + ] + }, { "id":"mikhail_andor1", "message":"As I said, Andor went out yesterday and hasn't been back since. I'm starting to worry about him. Please go look for your brother, he said he would only be out a short while.", diff --git a/AndorsTrail/res/xml/crossglen.tmx b/AndorsTrail/res/xml/crossglen.tmx index f31a4bc9c..17565708d 100644 --- a/AndorsTrail/res/xml/crossglen.tmx +++ b/AndorsTrail/res/xml/crossglen.tmx @@ -1,245 +1,274 @@ - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - eJztl0EOgjAQRRtdGNmybPQGcmKvIMYTQK+gl0AvAO5sI4RhnGkb6cjGxQtYSl87ob+xXClVWozl6qHq+1Gc+z6nQJ/LdoRq44Dj1gAD5lYTRHlzgv5ZhTwDcDyuVibgNfkneNyY2oTA3kYrdQc8dBpPyNtaz3qjVKffPAW9uPa/IPZb/ntlvLvMj5R3b8cusukV3kt5sQv/TuXFNTxkflJ5yRpSWY1yk20PPIdeXEMqq3FeT9oJuPdK5IXrxVlN5jXjIOeCvG7NBeFt9ZjTQ2bjvIYOPEeHb73O++0304A6dAQNU6e558JwfnHnVsuca855WyArl3CSeyy0HxMSs08liNqnAsTs0z/zcLlxZJD2xv6XSskLbjmFEg== + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + - - + + - + - + - + - + - + - + - - + + - + - - - - + + + + - - - + + + - \ No newline at end of file + diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java index c38814586..75fb14228 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java @@ -239,8 +239,10 @@ public final class ConversationActivity } else { conversation.nameColor = getSpanColor(R.attr.ui_theme_npcname_dark_color); } - }else{ + } else if (conversation.isReward) { conversation.textColor = getSpanColor(R.attr.ui_theme_reward_light_color); + } else { + conversation.textColor = getSpanColor(R.attr.ui_theme_dialogue_dark_color);; } numberOfNewMessage--; } @@ -256,12 +258,12 @@ public final class ConversationActivity } else { if (rb == null) return; Reply r = (Reply) rb.getTag(); - addConversationStatement(player, rb.getText().toString(), getSpanColor(R.attr.ui_theme_dialogue_light_color)); + addConversationStatement(player, rb.getText().toString(), getSpanColor(R.attr.ui_theme_dialogue_light_color), false); conversationState.playerSelectedReply(getResources(), r); } } - private void addConversationStatement(Actor actor, String text, int textColor) { + private void addConversationStatement(Actor actor, String text, int textColor, boolean isReward) { ConversationStatement s = new ConversationStatement(); if (actor != null) { s.iconID = actor.iconID; @@ -273,6 +275,7 @@ public final class ConversationActivity s.nameColor = actor == player ? getSpanColor(R.attr.ui_theme_playername_light_color) : getSpanColor(R.attr.ui_theme_npcname_light_color); s.textColor = textColor; s.isPlayerActor = actor != null && actor == player; + s.isReward = isReward; conversationHistory.add(s); numberOfNewMessage++; statementList.clearFocus(); @@ -296,6 +299,7 @@ public final class ConversationActivity public int nameColor; public int textColor; public boolean isPlayerActor; + public boolean isReward; public boolean hasActor() { return iconID != NO_ICON; @@ -312,6 +316,7 @@ public final class ConversationActivity dest.writeInt(nameColor); dest.writeInt(textColor); dest.writeByte((byte) (isPlayerActor ? 1 : 0)); + dest.writeByte((byte) (isReward ? 1 : 0)); } @SuppressWarnings("unused") @@ -325,6 +330,7 @@ public final class ConversationActivity result.nameColor = in.readInt(); result.textColor = in.readInt(); result.isPlayerActor = in.readByte() == 1; + result.isReward = in.readByte() == 1; return result; } @@ -391,7 +397,7 @@ public final class ConversationActivity @Override public void onTextPhraseReached(String message, Actor actor, String phraseID) { - addConversationStatement(actor, message, getSpanColor(R.attr.ui_theme_dialogue_light_color)); + addConversationStatement(actor, message, getSpanColor(R.attr.ui_theme_dialogue_light_color), false); } @Override @@ -427,7 +433,7 @@ public final class ConversationActivity } private void addRewardMessage(String text) { - addConversationStatement(null, text, getSpanColor(R.attr.ui_theme_reward_light_color)); + addConversationStatement(null, text, getSpanColor(R.attr.ui_theme_reward_light_color), true); } @Override diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java index 99e63c88d..d1214ede7 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java @@ -94,6 +94,9 @@ public final class ConversationController { case alignmentChange: addAlignmentReward(player, effect.effectID, effect.value); break; + case alignmentSet: + setAlignmentReward(player, effect.effectID, effect.value); + break; case giveItem: addItemReward(effect.effectID, effect.value, result); break; @@ -172,6 +175,11 @@ public final class ConversationController { MovementController.refreshMonsterAggressiveness(world.model.currentMap, world.model.player); } + private void setAlignmentReward(Player player, String faction, int delta) { + player.setAlignment(faction, delta); + MovementController.refreshMonsterAggressiveness(world.model.currentMap, world.model.player); + } + private void addQuestProgressReward(Player player, String questID, int questProgress, ScriptEffectResult result) { QuestProgress progress = new QuestProgress(questID, questProgress); boolean added = player.addQuestProgress(progress); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java index 50f4dda92..96f391901 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java @@ -204,7 +204,10 @@ public final class MapController { hasUpdated = true; } } - map.lastSeenLayoutHash = tileMap.getCurrentLayoutHash(); + if (map.lastSeenLayoutHash != tileMap.getCurrentLayoutHash()) { + map.lastSeenLayoutHash = tileMap.getCurrentLayoutHash(); + hasUpdated = true; + } return hasUpdated; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java index 2759de0bb..117c5e188 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java @@ -52,21 +52,23 @@ public final class MonsterMovementController implements EvaluateWalkable { } } - public static boolean monsterCanMoveTo(final Monster movingMonster, final PredefinedMap map, final LayeredTileMap tilemap, final CoordRect p) { + public static boolean monsterCanMoveTo(final Monster movingMonster, final PredefinedMap map, final LayeredTileMap tilemap, final CoordRect p, boolean ignoreAreas) { if (tilemap != null) { if (!tilemap.isWalkable(p)) return false; } if (map.getMonsterAt(p, movingMonster) != null) return false; - for (MapObject mObj : map.eventObjects) { - if (mObj == null) continue; - if (!mObj.isActive) continue; - if (!mObj.position.intersects(p)) continue; - switch (mObj.type) { + if (!ignoreAreas) { + for (MapObject mObj : map.eventObjects) { + if (mObj == null) continue; + if (!mObj.isActive) continue; + if (!mObj.position.intersects(p)) continue; + switch (mObj.type) { case newmap: case keyarea: case rest: return false; + } } } return true; @@ -82,7 +84,7 @@ public final class MonsterMovementController implements EvaluateWalkable { } else { determineMonsterNextPosition(m, area, world.model.player.position); - if (!monsterCanMoveTo(m, map, tileMap, m.nextPosition)) { + if (!monsterCanMoveTo(m, map, tileMap, m.nextPosition, area.ignoreAreas)) { cancelCurrentMonsterMovement(m); return; } @@ -152,12 +154,12 @@ public final class MonsterMovementController implements EvaluateWalkable { private final PathFinder pathfinder = new PathFinder(Constants.MAX_MAP_WIDTH, Constants.MAX_MAP_HEIGHT, this); public boolean findPathFor(Monster m, Coord to) { - return pathfinder.findPathBetween(m.rectPosition, to, m.nextPosition); + return pathfinder.findPathBetween(m.rectPosition, to, m.nextPosition, m); } @Override - public boolean isWalkable(CoordRect r) { - return monsterCanMoveTo(null, world.model.currentMap, world.model.currentTileMap, r); + public boolean isWalkable(CoordRect r, Monster m) { + return monsterCanMoveTo(null, world.model.currentMap, world.model.currentTileMap, r, m.area.ignoreAreas); } public void moveMonsterToNextPosition(final Monster m, final PredefinedMap map) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java index 830c0437e..969bab4e1 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java @@ -51,20 +51,20 @@ public final class MonsterSpawningController { } public boolean TEST_spawnInArea(PredefinedMap map, LayeredTileMap tileMap, MonsterSpawnArea a, MonsterType type) { return spawnInArea(map, tileMap, a, type, null); } private boolean spawnInArea(PredefinedMap map, LayeredTileMap tileMap, MonsterSpawnArea a, MonsterType type, Coord playerPosition) { - Coord p = getRandomFreePosition(map, tileMap, a.area, type.tileSize, playerPosition); + Coord p = getRandomFreePosition(map, tileMap, a, type.tileSize, playerPosition); if (p == null) return false; Monster m = a.spawn(p, type); monsterSpawnListeners.onMonsterSpawned(map, m); return true; } - public static Coord getRandomFreePosition(PredefinedMap map, LayeredTileMap tileMap, CoordRect area, Size requiredSize, Coord playerPosition) { + public static Coord getRandomFreePosition(PredefinedMap map, LayeredTileMap tileMap, MonsterSpawnArea a, Size requiredSize, Coord playerPosition) { CoordRect p = new CoordRect(requiredSize); for(int i = 0; i < 100; ++i) { p.topLeft.set( - area.topLeft.x + Constants.rnd.nextInt(area.size.width) - ,area.topLeft.y + Constants.rnd.nextInt(area.size.height)); - if (!MonsterMovementController.monsterCanMoveTo(null, map, tileMap, p)) continue; + a.area.topLeft.x + Constants.rnd.nextInt(a.area.size.width) + ,a.area.topLeft.y + Constants.rnd.nextInt(a.area.size.height)); + if (!MonsterMovementController.monsterCanMoveTo(null, map, tileMap, p, a.ignoreAreas)) continue; if (playerPosition != null && p.contains(playerPosition)) continue; return p.topLeft; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java index 0830b2637..8164c1f00 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java @@ -284,7 +284,7 @@ public final class MovementController implements TimedMessageTask.Callback { for (MonsterSpawnArea a : map.spawnAreas) { for (Monster m : a.monsters) { if (tileMap.isWalkable(m.rectPosition)) continue; - Coord p = MonsterSpawningController.getRandomFreePosition(map, tileMap, a.area, m.tileSize, playerPosition); + Coord p = MonsterSpawningController.getRandomFreePosition(map, tileMap, a, m.tileSize, playerPosition); if (p == null) continue; m.position.set(p); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java index 7a3b22ec0..e82f46303 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java @@ -2,6 +2,7 @@ package com.gpl.rpg.AndorsTrail.controller; import java.util.Arrays; +import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.util.Coord; import com.gpl.rpg.AndorsTrail.util.CoordRect; @@ -21,10 +22,10 @@ public class PathFinder { } public interface EvaluateWalkable { - public boolean isWalkable(CoordRect r); + public boolean isWalkable(CoordRect r, Monster m); } - public boolean findPathBetween(final CoordRect from, final Coord to, CoordRect nextStep) { + public boolean findPathBetween(final CoordRect from, final Coord to, CoordRect nextStep, Monster m) { int iterations = 0; if (from.contains(to)) return false; @@ -44,19 +45,19 @@ public class PathFinder { if (from.isAdjacentTo(p)) return true; - p.x -= 1; visit(nextStep, measureDistanceTo); - p.x += 2; visit(nextStep, measureDistanceTo); - p.x -= 1; p.y -= 1; visit(nextStep, measureDistanceTo); - p.y += 2; visit(nextStep, measureDistanceTo); - p.x -= 1; visit(nextStep, measureDistanceTo); - p.x += 2; visit(nextStep, measureDistanceTo); - p.y -= 2; visit(nextStep, measureDistanceTo); - p.x -= 2; visit(nextStep, measureDistanceTo); + p.x -= 1; visit(nextStep, measureDistanceTo, m); + p.x += 2; visit(nextStep, measureDistanceTo, m); + p.x -= 1; p.y -= 1; visit(nextStep, measureDistanceTo, m); + p.y += 2; visit(nextStep, measureDistanceTo, m); + p.x -= 1; visit(nextStep, measureDistanceTo, m); + p.x += 2; visit(nextStep, measureDistanceTo, m); + p.y -= 2; visit(nextStep, measureDistanceTo, m); + p.x -= 2; visit(nextStep, measureDistanceTo, m); } return false; } - private void visit(CoordRect r, Coord measureDistanceTo) { + private void visit(CoordRect r, Coord measureDistanceTo, Monster m) { final int x = r.topLeft.x; final int y = r.topLeft.y; @@ -68,7 +69,7 @@ public class PathFinder { final int i = (y * maxWidth) + x; if (visited[i]) return; visited[i] = true; - if (!map.isWalkable(r)) return; + if (!map.isWalkable(r, m)) return; int dx = (measureDistanceTo.x - x); int dy = (measureDistanceTo.y - y); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java index e7e67dd2f..303dbb5b7 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java @@ -67,7 +67,7 @@ public final class VisualEffectController { public final class SpriteMoveAnimation extends Handler implements Runnable { - private static final int millisecondsPerFrame=25; +// private static final int millisecondsPerFrame=25; private final VisualEffectCompletedCallback callback; private final int callbackValue; @@ -80,12 +80,12 @@ public final class VisualEffectController { @Override public void run() { - update(); - if (System.currentTimeMillis() - actor.vfxStartTime >= duration) { - onCompleted(); - } else { - postDelayed(this, millisecondsPerFrame); - } + onCompleted(); +// update(); +// if (System.currentTimeMillis() - actor.vfxStartTime >= duration) { +// } else { +// postDelayed(this, millisecondsPerFrame); +// } } public SpriteMoveAnimation(Coord origin, Coord destination, int duration, Actor actor, VisualEffectCompletedCallback callback, int callbackValue) { @@ -98,10 +98,10 @@ public final class VisualEffectController { } - private void update() { - - visualEffectFrameListeners.onNewSpriteMoveFrame(this); - } +// private void update() { +// +// visualEffectFrameListeners.onNewSpriteMoveFrame(this); +// } private void onCompleted() { --effectCount; @@ -115,8 +115,11 @@ public final class VisualEffectController { actor.hasVFXRunning = true; actor.vfxDuration = duration; actor.vfxStartTime = System.currentTimeMillis(); + visualEffectFrameListeners.onSpriteMoveStarted(this); if (duration == 0 || !controllers.preferences.enableUiAnimations) onCompleted(); - else postDelayed(this, 0); + else { + postDelayed(this, duration); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java index c794c8624..bbe226cc5 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java @@ -6,6 +6,7 @@ import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAni public interface VisualEffectFrameListener { void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset); void onAnimationCompleted(VisualEffectAnimation animation); + void onSpriteMoveStarted(SpriteMoveAnimation animation); void onNewSpriteMoveFrame(SpriteMoveAnimation animation); void onSpriteMoveCompleted(SpriteMoveAnimation animation); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java index 48a756c0e..6b5d5fca8 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java @@ -14,6 +14,10 @@ public final class VisualEffectFrameListeners extends ListOfListeners onSpriteMoveStarted = new Function1() { + @Override public void call(VisualEffectFrameListener listener, SpriteMoveAnimation animation) { listener.onSpriteMoveStarted(animation); } + }; + private final Function1 onNewSpriteMoveFrame = new Function1() { @Override public void call(VisualEffectFrameListener listener, SpriteMoveAnimation animation) { listener.onNewSpriteMoveFrame(animation); } }; @@ -32,6 +36,11 @@ public final class VisualEffectFrameListeners extends ListOfListeners= 25) readCombatTraits = src.readBoolean(); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/MonsterTypeCollection.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/MonsterTypeCollection.java index 296e5a17c..870afcfba 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/MonsterTypeCollection.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/MonsterTypeCollection.java @@ -24,7 +24,11 @@ public final class MonsterTypeCollection { for (MonsterType t : monsterTypesById.values()) { if (t.spawnGroup.equalsIgnoreCase(spawnGroup)) result.add(t); } - + //If the spawnGroup is empty, it should be a direct reference to a MonsterType's id. + if (result.isEmpty()) { + MonsterType t = monsterTypesById.get(spawnGroup); + if (t != null) result.add(t); + } return result; } @@ -38,9 +42,4 @@ public final class MonsterTypeCollection { public void initialize(MonsterTypeParser parser, String input) { parser.parseRows(input, monsterTypesById); } - - // Unit test method. Not part of the game logic. - public HashMap UNITTEST_getAllMonsterTypes() { - return monsterTypesById; - } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java index d53b805f7..b8a466634 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java @@ -202,6 +202,9 @@ public final class Player extends Actor { if (v == null) return 0; return v; } + public void setAlignment(String faction, int newValue) { + alignments.put(faction, newValue); + } public void addAlignment(String faction, int delta) { int newValue = getAlignment(faction) + delta; alignments.put(faction, newValue); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapSection.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapSection.java index fa95a1d6e..3fa84fd2d 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapSection.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapSection.java @@ -7,6 +7,7 @@ public final class MapSection { public final MapLayer layerGround; public final MapLayer layerObjects; public final MapLayer layerAbove; + public final MapLayer layerTop; public final boolean[][] isWalkable; private final byte[] layoutHash; @@ -14,12 +15,14 @@ public final class MapSection { MapLayer layerGround , MapLayer layerObjects , MapLayer layerAbove + , MapLayer layerTop , boolean[][] isWalkable , byte[] layoutHash ) { this.layerGround = layerGround; this.layerObjects = layerObjects; this.layerAbove = layerAbove; + this.layerTop = layerTop; this.isWalkable = isWalkable; this.layoutHash = layoutHash; } @@ -28,6 +31,7 @@ public final class MapSection { replaceTileLayerSection(layerGround, replaceLayersWith.layerGround, replacementArea); replaceTileLayerSection(layerObjects, replaceLayersWith.layerObjects, replacementArea); replaceTileLayerSection(layerAbove, replaceLayersWith.layerAbove, replacementArea); + replaceTileLayerSection(layerTop, replaceLayersWith.layerTop, replacementArea); if (replaceLayersWith.isWalkable != null) { final int dy = replacementArea.topLeft.y; final int height = replacementArea.size.height; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java index b59f4a548..72b71ba37 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java @@ -21,6 +21,7 @@ public final class MonsterSpawnArea { public final String[] monsterTypeIDs; public final ArrayList monsters = new ArrayList(); public final boolean isUnique; // unique == non-respawnable + public final boolean ignoreAreas; //Can spawn on other game objects area. private final String group; public boolean isSpawning; public final boolean isSpawningForNewGame; @@ -32,6 +33,7 @@ public final class MonsterSpawnArea { , String areaID , String[] monsterTypeIDs , boolean isUnique + , boolean ignoreAreas , String group , boolean isSpawningForNewGame ) { @@ -41,6 +43,7 @@ public final class MonsterSpawnArea { this.areaID = areaID; this.monsterTypeIDs = monsterTypeIDs; this.isUnique = isUnique; + this.ignoreAreas = ignoreAreas; this.group = group; this.isSpawningForNewGame = isSpawningForNewGame; this.isSpawning = isSpawningForNewGame; @@ -79,7 +82,7 @@ public final class MonsterSpawnArea { spawn(p, context.monsterTypes.getMonsterType(monsterTypeID)); } public Monster spawn(Coord p, MonsterType type) { - Monster m = new Monster(type); + Monster m = new Monster(type, this); m.position.set(p); monsters.add(m); quantity.current++; @@ -125,7 +128,7 @@ public final class MonsterSpawnArea { if (fileversion >= 41) isSpawning = src.readBoolean(); quantity.current = src.readInt(); for(int i = 0; i < quantity.current; ++i) { - monsters.add(Monster.newFromParcel(src, world, fileversion)); + monsters.add(Monster.newFromParcel(src, world, fileversion, this)); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java index d1f282dd8..098bb72c6 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java @@ -109,6 +109,7 @@ public final class TMXMapTranslator { mapObjects.add(MapObject.createMapChangeArea(position, object.name, map, place, group.name)); } else if (object.type.equalsIgnoreCase("spawn")) { boolean isActiveForNewGame = true; + boolean ignoreAreas = false; int maxQuantity = 1; int spawnChance = 10; String spawnGroup = object.name; @@ -125,6 +126,8 @@ public final class TMXMapTranslator { spawnChance = Integer.parseInt(p.value); } else if (p.name.equalsIgnoreCase("active")) { isActiveForNewGame = Boolean.parseBoolean(p.value); + } else if (p.name.equalsIgnoreCase("ignoreAreas")) { + ignoreAreas = Boolean.parseBoolean(p.value); } else if (p.name.equalsIgnoreCase("spawngroup")) { spawnGroup = p.value; } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { @@ -152,6 +155,7 @@ public final class TMXMapTranslator { ,object.name ,monsterTypeIDs ,isUnique + ,ignoreAreas ,group.name ,isActiveForNewGame ); @@ -256,9 +260,10 @@ public final class TMXMapTranslator { 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_TOP = "top"; private static final String LAYERNAME_WALKABLE = "walkable"; private static final String PROPNAME_FILTER = "colorfilter"; - private static final SetOfLayerNames defaultLayerNames = new SetOfLayerNames(LAYERNAME_GROUND, LAYERNAME_OBJECTS, LAYERNAME_ABOVE, LAYERNAME_WALKABLE); + private static final SetOfLayerNames defaultLayerNames = new SetOfLayerNames(LAYERNAME_GROUND, LAYERNAME_OBJECTS, LAYERNAME_ABOVE, LAYERNAME_TOP, LAYERNAME_WALKABLE); private static LayeredTileMap transformMap(TMXLayerMap map, TileCache tileCache) { final Size mapSize = new Size(map.width, map.height); @@ -303,6 +308,7 @@ public final class TMXMapTranslator { 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_TOP)) layerNames.topLayersName = prop.value; else if (prop.name.equalsIgnoreCase(LAYERNAME_WALKABLE)) layerNames.walkableLayersName = prop.value; else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { if (!requirementPropertiesNames.contains(prop.name)) @@ -344,9 +350,10 @@ public final class TMXMapTranslator { 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); + final MapLayer layerTop = transformMapLayer(layersPerLayerName, layerNames.topLayersName, 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); + return new MapSection(layerGround, layerObjects, layerAbove, layerTop, isWalkable, layoutHash); } private static TMXLayer findLayer(HashMap layersPerLayerName, String layerName, String mapName) { @@ -447,17 +454,20 @@ public final class TMXMapTranslator { public String groundLayerName; public String objectsLayerName; public String aboveLayersName; + public String topLayersName; public String walkableLayersName; public SetOfLayerNames() { this.groundLayerName = null; this.objectsLayerName = null; this.aboveLayersName = null; + this.topLayersName = null; this.walkableLayersName = null; } - public SetOfLayerNames(String groundLayerName, String objectsLayerName, String aboveLayersName, String walkableLayersName) { + public SetOfLayerNames(String groundLayerName, String objectsLayerName, String aboveLayersName, String topLayersName, String walkableLayersName) { this.groundLayerName = groundLayerName; this.objectsLayerName = objectsLayerName; this.aboveLayersName = aboveLayersName; + this.topLayersName = topLayersName; this.walkableLayersName = walkableLayersName; } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/ScriptEffect.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/ScriptEffect.java index 1cffcff6a..1284531ca 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/ScriptEffect.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/ScriptEffect.java @@ -8,6 +8,7 @@ public final class ScriptEffect { , actorCondition , actorConditionImmunity , alignmentChange + , alignmentSet , giveItem , createTimer , spawnAll diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java index a0620fd34..4729a6275 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java @@ -5,11 +5,12 @@ import java.io.IOException; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; +import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; import com.gpl.rpg.AndorsTrail.util.Coord; public final class LegacySavegameFormatReaderForMonster { - public static Monster newFromParcel_pre_v25(DataInputStream src, int fileversion, MonsterType monsterType) throws IOException { - Monster m = new Monster(monsterType); + public static Monster newFromParcel_pre_v25(DataInputStream src, int fileversion, MonsterType monsterType, MonsterSpawnArea area) throws IOException { + Monster m = new Monster(monsterType, area); m.position.set(new Coord(src, fileversion)); m.ap.current = src.readInt(); m.health.current = src.readInt(); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java index 60297f0d2..9a8f4a547 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java @@ -1,5 +1,7 @@ package com.gpl.rpg.AndorsTrail.view; +import java.lang.ref.WeakReference; + import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -40,6 +42,7 @@ import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection; import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; 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.Size; public final class MainView extends SurfaceView @@ -91,9 +94,6 @@ public final class MainView extends SurfaceView private LayeredTileMap currentTileMap; private TileCollection tiles; - private Bitmap groundBitmap = null; -// private Bitmap objectsBitmap = null; - private Bitmap aboveBitmap = null; private final Coord playerPosition = new Coord(); private Size surfaceSize; private boolean redrawNextTick = false; @@ -103,6 +103,8 @@ public final class MainView extends SurfaceView private long scrollStartTime; //TODO restore private final modifiers before release public static long SCROLL_DURATION = Constants.MINIMUM_INPUT_INTERVAL; + private int movingSprites = 0; + private SpriteMoveAnimationHandler movingSpritesRedrawTick = new SpriteMoveAnimationHandler(this); public MainView(Context context, AttributeSet attr) { @@ -178,6 +180,7 @@ public final class MainView extends SurfaceView @Override public void surfaceDestroyed(SurfaceHolder sh) { hasSurface = false; + movingSpritesRedrawTick.stop(); } @Override @@ -208,7 +211,7 @@ public final class MainView extends SurfaceView } private static enum RedrawAllDebugReason { - SurfaceChanged, MapChanged, PlayerMoved, MapScrolling, FilterAnimation + SurfaceChanged, MapChanged, PlayerMoved, SpriteMoved, MapScrolling, FilterAnimation } private static enum RedrawAreaDebugReason { MonsterMoved, MonsterKilled, EffectCompleted @@ -219,6 +222,7 @@ public final class MainView extends SurfaceView private void redrawAll(RedrawAllDebugReason why) { if (scrolling && why != RedrawAllDebugReason.MapScrolling) return; + if (!scrolling && movingSprites > 0 && why != RedrawAllDebugReason.SpriteMoved) return; redrawArea_(mapViewArea, null, 0, 0); } private void redrawTile(final Coord p, RedrawTileDebugReason why) { @@ -435,11 +439,8 @@ public final class MainView extends SurfaceView } private void doDrawRect_Ground(Canvas canvas, CoordRect area) { - if (!tryDrawMapBitmap(canvas, area, groundBitmap)) { - drawMapLayer(canvas, area, currentTileMap.currentLayout.layerGround); - tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerObjects); - } - + drawMapLayer(canvas, area, currentTileMap.currentLayout.layerGround); + tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerObjects); } private void doDrawRect_Objects(Canvas canvas, CoordRect area) { @@ -482,9 +483,8 @@ public final class MainView extends SurfaceView } private void doDrawRect_Above(Canvas canvas, CoordRect area) { - if (!tryDrawMapBitmap(canvas, area, aboveBitmap)) { - tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerAbove); - } + tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerAbove); + tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerTop); if (model.uiSelections.selectedPosition != null) { if (model.uiSelections.selectedMonster != null) { @@ -495,18 +495,6 @@ public final class MainView extends SurfaceView } } - private boolean tryDrawMapBitmap(Canvas canvas, final CoordRect area, final Bitmap bitmap) { - if (bitmap != null) { - drawMapBitmap(canvas, area, bitmap); - return true; - } - return false; - } - - private void drawMapBitmap(Canvas canvas, final CoordRect area, final Bitmap bitmap){ - canvas.drawBitmap(bitmap, -mapViewArea.topLeft.x * tileSize, -mapViewArea.topLeft.y * tileSize, mPaint); - } - private void tryDrawMapLayer(Canvas canvas, final CoordRect area, final MapLayer layer) { if (layer != null) drawMapLayer(canvas, area, layer); } @@ -530,25 +518,6 @@ public final class MainView extends SurfaceView } } - private void drawMapLayerOffscreen(Canvas canvas, final MapLayer layer) { - int my = 0; - int py = 0; - int px0 = 0; - for (int y = 0; y < currentMap.size.height; ++y, ++my, py += tileSize) { - int mx = 0; - if (my < 0) continue; - if (my >= currentMap.size.height) break; - int px = px0; - for (int x = 0; x < currentMap.size.width; ++x, ++mx, px += tileSize) { - if (mx < 0) continue; - if (mx >= currentMap.size.width) break; - final int tile = layer.tiles[mx][my]; - if (tile == 0) continue; - tiles.drawTile(canvas, tile, px, py, mPaint); - } - } - } - private void drawFromMapPosition(Canvas canvas, final CoordRect area, final Coord p, final int tile) { if (!area.contains(p)) return; _drawFromMapPosition(canvas, area, p.x, p.y, tile); @@ -574,11 +543,12 @@ public final class MainView extends SurfaceView @Override public void onPlayerEnteredNewMap(PredefinedMap map, Coord p) { + movingSpritesRedrawTick.start(); synchronized (holder) { currentMap = map; currentTileMap = model.currentTileMap; tiles = world.tileManager.currentMapTiles; - + movingSprites = 0; Size visibleNumberOfTiles = new Size( Math.min(screenSizeTileCount.width, currentMap.size.width) ,Math.min(screenSizeTileCount.height, currentMap.size.height) @@ -604,8 +574,6 @@ public final class MainView extends SurfaceView clearCanvas(); - updateBitmaps(); - recalculateMapTopLeft(model.player.position, false); redrawAll(RedrawAllDebugReason.MapChanged); } @@ -629,7 +597,7 @@ public final class MainView extends SurfaceView if (allowScrolling) { if (mapTopLeft.x != oldX || mapTopLeft.y != oldY) { scrollVector = new Coord(mapTopLeft.x - oldX, mapTopLeft.y - oldY); - new ScrollAnimationHandler().start(); + new ScrollAnimationHandler(this).start(); } } else { scrolling = false; @@ -641,63 +609,22 @@ public final class MainView extends SurfaceView worldCoordsToScreenCords(mapViewArea, redrawClip); } -// private void printMem() { -// Runtime r = Runtime.getRuntime(); -// L.log("---------------------------------------"); -// L.log("Max : "+r.maxMemory()/1024); -// L.log("Tot : "+r.totalMemory()/1024); -// L.log("Use : "+(r.totalMemory()-r.freeMemory())/1024); -// L.log("Fre : "+r.freeMemory()/1024); -// } - - private void updateBitmaps() { - - //CPU and pixel fill-rate optimization, but makes low heap-size devices throw an OutOfMemoryError... disabled for now. -// Canvas bitmapDrawingCanvas; -// -// printMem(); -// -// if (groundBitmap != null) { -// groundBitmap.recycle(); -// groundBitmap = null; -// } -// if (aboveBitmap != null) { -// aboveBitmap.recycle(); -// aboveBitmap = null; -// } -// -// System.gc(); -// -// long freeMemRequired = tileSize * tileSize * currentMap.size.width * currentMap.size.height * 4 /*RGBA_8888*/ * 3 /*Require three times the needed size, to leave room for others*/; -// Runtime r = Runtime.getRuntime(); -// -// if (currentTileMap.currentLayout.layerGround != null && r.maxMemory() - r.totalMemory() > freeMemRequired) { -// groundBitmap = Bitmap.createBitmap(currentMap.size.width * tileSize, currentMap.size.height * tileSize, Config.ARGB_8888); -// bitmapDrawingCanvas = new Canvas(groundBitmap); -// drawMapLayerOffscreen(bitmapDrawingCanvas, currentTileMap.currentLayout.layerGround); -// if (currentTileMap.currentLayout.layerObjects != null) { -// drawMapLayerOffscreen(bitmapDrawingCanvas, currentTileMap.currentLayout.layerObjects); -// } -// } -// -// -// if (currentTileMap.currentLayout.layerAbove != null && r.maxMemory() - r.totalMemory() > freeMemRequired) { -// aboveBitmap = Bitmap.createBitmap(currentMap.size.width * tileSize, currentMap.size.height * tileSize, Config.ARGB_8888); -// bitmapDrawingCanvas = new Canvas(aboveBitmap); -// drawMapLayerOffscreen(bitmapDrawingCanvas, currentTileMap.currentLayout.layerAbove); -// } - -// printMem(); -// - } - public final class ScrollAnimationHandler extends Handler implements Runnable { + public static final class ScrollAnimationHandler extends Handler implements Runnable { private static final int FRAME_DURATION = 40; + + private final WeakReference view; + + public ScrollAnimationHandler(MainView view) { + this.view = new WeakReference(view); + } @Override public void run() { - if (System.currentTimeMillis() - scrollStartTime >= SCROLL_DURATION) { + MainView v = view.get(); + if (v == null) return; + if (System.currentTimeMillis() - v.scrollStartTime >= SCROLL_DURATION) { onCompleted(); } else { postDelayed(this, FRAME_DURATION); @@ -706,22 +633,77 @@ public final class MainView extends SurfaceView } private void update() { - redrawAll(RedrawAllDebugReason.MapScrolling); + MainView v = view.get(); + if (v == null) return; + v.redrawAll(RedrawAllDebugReason.MapScrolling); } private void onCompleted() { - scrolling = false; - scrollVector = null; + MainView v = view.get(); + if (v == null) return; + v.scrolling = false; + v.scrollVector = null; } public void start() { - scrolling = true; - scrollStartTime = System.currentTimeMillis(); + MainView v = view.get(); + if (v == null) return; + v.scrolling = true; + v.scrollStartTime = System.currentTimeMillis(); postDelayed(this, 0); } } + public static final class SpriteMoveAnimationHandler extends Handler implements Runnable { + + private static final int FRAME_DURATION = 40; + private final WeakReference view; + private boolean stop = true; + + public SpriteMoveAnimationHandler(MainView view) { + this.view = new WeakReference(view); + } + + @Override + public void run() { + if (!stop) postDelayed(this, FRAME_DURATION); + update(); + } + + private void update() { +// L.log("stop="+stop+" - scroll="+scrolling+" - moving="+movingSprites); + if (stop) return; + MainView v = view.get(); + if (v == null) return; + if (!v.scrolling) { + if (v.movingSprites > 0) { + //TODO : limit redraw area when shouldRedrawEverything() returns false. + //Implies keeping track of the animation bounding box in a thread-safe way... :'( + v.redrawAll(RedrawAllDebugReason.SpriteMoved); + } + } + synchronized (this) { + if (v.movingSprites <= 0) stop(); + } + } + + public void start() { + if (stop) { + stop = false; + MainView v = view.get(); + if (v == null) return; + if (v.controllers.preferences.enableUiAnimations) postDelayed(this, 0); + } + } + + public void stop() { + stop = true; + } + } + + + @Override public void onPlayerMoved(Coord newPosition, Coord previousPosition) { recalculateMapTopLeft(newPosition, preferences.enableUiAnimations); @@ -829,7 +811,6 @@ public final class MainView extends SurfaceView @Override public void onMapTilesChanged(PredefinedMap map, LayeredTileMap tileMap) { if (map != currentMap) return; - updateBitmaps(); currentTileMap.setColorFilter(this.mPaint); redrawAll(RedrawAllDebugReason.MapChanged); } @@ -843,14 +824,23 @@ public final class MainView extends SurfaceView public void onAnimationCompleted(VisualEffectAnimation animation) { redrawArea(animation.area, RedrawAreaDebugReason.EffectCompleted); } + + @Override + public void onSpriteMoveStarted(SpriteMoveAnimation animation) { + synchronized (movingSpritesRedrawTick) { + movingSprites++; + movingSpritesRedrawTick.start(); + } + } @Override public void onNewSpriteMoveFrame(SpriteMoveAnimation animation) { - redrawMoveArea_(CoordRect.getBoundingRect(animation.origin, animation.destination, animation.actor.tileSize), animation); + //redrawMoveArea_(CoordRect.getBoundingRect(animation.origin, animation.destination, animation.actor.tileSize), animation); } @Override public void onSpriteMoveCompleted(SpriteMoveAnimation animation) { + movingSprites--; redrawArea(CoordRect.getBoundingRect(animation.origin, animation.destination, animation.actor.tileSize), RedrawAreaDebugReason.EffectCompleted); }