diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java index 9777a42c4..3df37a8a9 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 8c8d6bbce..34149225a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java @@ -7,6 +7,7 @@ import com.gpl.rpg.AndorsTrail.util.CoordRect; 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); void onAsyncAreaUpdate(CoordRect area); 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 4abe7d0f5..cbeb221bb 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java @@ -15,6 +15,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); } }; @@ -37,6 +41,11 @@ public final class VisualEffectFrameListeners extends ListOfListeners UNITTEST_getAllMonsterTypes() { - return monsterTypesById; - } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java index 13be68be7..d533cde95 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; @@ -104,6 +104,9 @@ public final class MainView extends SurfaceView //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) { super(context, attr); @@ -178,6 +181,7 @@ public final class MainView extends SurfaceView @Override public void surfaceDestroyed(SurfaceHolder sh) { hasSurface = false; + movingSpritesRedrawTick.stop(); } @Override @@ -208,7 +212,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, AsyncRequest @@ -219,6 +223,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 +440,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) { @@ -494,18 +496,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); } @@ -529,25 +519,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); @@ -573,11 +544,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) @@ -603,8 +575,6 @@ public final class MainView extends SurfaceView clearCanvas(); - updateBitmaps(); - recalculateMapTopLeft(model.player.position, false); redrawAll(RedrawAllDebugReason.MapChanged); } @@ -628,7 +598,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; @@ -640,63 +610,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); @@ -705,22 +634,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); @@ -828,7 +812,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); } @@ -842,14 +825,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); }