diff --git a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java index b88b7a3c0..62abe3553 100644 --- a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java +++ b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java @@ -19,20 +19,25 @@ import com.gpl.rpg.AndorsTrail.resource.VisualEffectCollection.VisualEffect; 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; import java.util.ArrayList; import java.util.List; public final class VisualEffectController { + private static final long EFFECT_UPDATE_INTERVAL = 25; private int effectCount = 0; - private final List activeAnimations = new ArrayList<>(); + private final ControllerContext controllers; private final WorldContext world; private final VisualEffectCollection effectTypes; + private final Handler animationHandler = new Handler(); + private final List activeAnimations = new ArrayList<>(); public final VisualEffectFrameListeners visualEffectFrameListeners = new VisualEffectFrameListeners(); + private long getEffectUpdateInterval() { + return EFFECT_UPDATE_INTERVAL * controllers.preferences.attackspeed_milliseconds / AndorsTrailPreferences.ATTACKSPEED_DEFAULT_MILLISECONDS; + } public VisualEffectController(ControllerContext controllers, WorldContext world) { this.controllers = controllers; @@ -43,25 +48,41 @@ public final class VisualEffectController { public void startEffect(Coord position, VisualEffectCollection.VisualEffectID effectID, String displayValue, VisualEffectCompletedCallback callback, int callbackValue) { ++effectCount; VisualEffectAnimation animation = new VisualEffectAnimation(effectTypes.getVisualEffect(effectID), position, displayValue, callback, callbackValue); - activeAnimations.add(animation); animation.start(); } - public void collectAndSendAnimations(VisualEffectAnimation animation) { - List tileIDs = new ArrayList<>(); - List yOffsets = new ArrayList<>(); - //There are more elegant ways to fix this, but to get multiple effects to work, this is the quickest fix: increase all other effects that are being played - //TODO: if someone got time to make this look nice, be my guest - for (VisualEffectAnimation vanimation : activeAnimations) { - if (vanimation != animation && vanimation.currentFrame < vanimation.effect.lastFrame) vanimation.currentFrame++; - tileIDs.add(vanimation.effect.frameIconIDs[vanimation.currentFrame]); - yOffsets.add(-2 * vanimation.currentFrame); - L.log("VisualEffectController: collectAndSendAnimations: " + vanimation.currentFrame + " currentFrame, effectCount = " + effectCount); + private void startAnimation(VisualEffectAnimation animation) { + activeAnimations.add(animation); + animation.update(); + if (activeAnimations.size() == 1) { + animationHandler.postDelayed(animationRunnable, 0); } - L.log("VisualEffectController: collectAndSendAnimations: " + activeAnimations.size() + " animations to send, effectCount = " + effectCount); - visualEffectFrameListeners.onNewAnimationFrames(activeAnimations, tileIDs, yOffsets); } + private final Runnable animationRunnable = new Runnable() { + @Override + public void run() { + if(!activeAnimations.isEmpty()) { + long updateInterval = getEffectUpdateInterval(); + animationHandler.postDelayed(this, updateInterval); + + for (int i = 0; i < activeAnimations.size(); i++) { + VisualEffectAnimation animation = activeAnimations.get(i); + animation.durationPassed += updateInterval; + animation.updateFrame(); + animation.update(); + if (animation.currentFrame >= animation.effect.lastFrame) { + animation.onCompleted(); + activeAnimations.remove(i); + effectCount--; + i--; + } + } + visualEffectFrameListeners.onNewAnimationFrames(activeAnimations); + } + } + }; + private VisualEffectCollection.VisualEffectID enqueuedEffectID = null; private int enqueuedEffectValue = 0; public void enqueueEffect(VisualEffectCollection.VisualEffectID effectID, int displayValue) { @@ -85,10 +106,9 @@ public final class VisualEffectController { .start(); } - public final class SpriteMoveAnimation extends Handler implements Runnable { - -// private static final int millisecondsPerFrame=25; - + public final class SpriteMoveAnimation implements Runnable { + private final Handler handler = new Handler(); + private final VisualEffectCompletedCallback callback; private final int callbackValue; @@ -102,11 +122,6 @@ public final class VisualEffectController { @Override public void run() { onCompleted(); -// update(); -// if (System.currentTimeMillis() - actor.vfxStartTime >= duration) { -// } else { -// postDelayed(this, millisecondsPerFrame); -// } } public SpriteMoveAnimation(Coord origin, Coord destination, int duration, Actor actor, PredefinedMap map, VisualEffectCompletedCallback callback, int callbackValue) { @@ -119,11 +134,6 @@ public final class VisualEffectController { this.destination = destination; } - -// private void update() { -// -// visualEffectFrameListeners.onNewSpriteMoveFrame(this); -// } private void onCompleted() { --effectCount; @@ -132,7 +142,6 @@ public final class VisualEffectController { visualEffectFrameListeners.onSpriteMoveCompleted(this); } - public void start() { actor.hasVFXRunning = true; actor.vfxDuration = duration; @@ -140,12 +149,9 @@ public final class VisualEffectController { visualEffectFrameListeners.onSpriteMoveStarted(this); if (duration == 0 || !controllers.preferences.enableUiAnimations) onCompleted(); else { - postDelayed(this, duration); + handler.postDelayed(this, duration); } } - - - } public static final Paint textPaint = new Paint(); @@ -155,58 +161,41 @@ public final class VisualEffectController { textPaint.setTextAlign(Align.CENTER); } - public static class VisualEffectData { - public final VisualEffectAnimation effect; - public final int tileID; - public final int textYOffset; + public final class VisualEffectAnimation { + public int tileID; + public int textYOffset; + public long durationPassed = 0; - public VisualEffectData(VisualEffectAnimation effect, int tileID, int textYOffset) { - this.effect = effect; - this.tileID = tileID; - this.textYOffset = textYOffset; - } - } - - public final class VisualEffectAnimation extends Handler implements Runnable { - - @Override - public void run() { - if (currentFrame >= effect.lastFrame) { - onCompleted(); - } else { - postDelayed(this, effect.millisecondPerFrame * controllers.preferences.attackspeed_milliseconds / AndorsTrailPreferences.ATTACKSPEED_DEFAULT_MILLISECONDS); - update(); + private void updateFrame() { + long frameDuration = (long) effect.millisecondPerFrame * controllers.preferences.attackspeed_milliseconds / AndorsTrailPreferences.ATTACKSPEED_DEFAULT_MILLISECONDS; + while (durationPassed > frameDuration) { + currentFrame++; + durationPassed -= frameDuration; } } - private void update() { - ++currentFrame; - int frame = currentFrame; + if (currentFrame >= effect.lastFrame) { + return; + } -// int tileID = effect.frameIconIDs[frame]; -// int textYOffset = -2 * (frame); + tileID = effect.frameIconIDs[currentFrame]; + textYOffset = -2 * (currentFrame); - if (frame >= beginFadeAtFrame && displayText != null) { - textPaint.setAlpha(255 * (effect.lastFrame - frame) / (effect.lastFrame - beginFadeAtFrame)); + if (currentFrame >= beginFadeAtFrame && displayText != null) { + textPaint.setAlpha(255 * (effect.lastFrame - currentFrame) / (effect.lastFrame - beginFadeAtFrame)); } area.topLeft.y = position.y - 1; - - //Fall back to onNewAnimationFrame if the new effect handle process is no longer desired -// visualEffectFrameListeners.onNewAnimationFrame(this, tileID, textYOffset); - collectAndSendAnimations(this); } private void onCompleted() { - --effectCount; - activeAnimations.remove(this); visualEffectFrameListeners.onAnimationCompleted(this); if (callback != null) callback.onVisualEffectCompleted(callbackValue); } public void start() { if (!controllers.preferences.enableUiAnimations) onCompleted(); - else postDelayed(this, 0); + else startAnimation(this); } private int currentFrame = 0; @@ -235,7 +224,7 @@ public final class VisualEffectController { this.area = new CoordRect(new Coord(position.x - (widthNeededInTiles / 2), position.y - 1), new Size(widthNeededInTiles, 2)); this.beginFadeAtFrame = effect.lastFrame / 2; } - + public Paint getTextPaint(){ return textPaint; } diff --git a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java index 5d06aef20..35387b799 100644 --- a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java +++ b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java @@ -7,8 +7,7 @@ import com.gpl.rpg.AndorsTrail.util.CoordRect; import java.util.List; public interface VisualEffectFrameListener { - void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset); - void onNewAnimationFrames(List animations, List tileIDs, List textYOffsets); + void onNewAnimationFrames(List effects); void onAnimationCompleted(VisualEffectAnimation animation); void onSpriteMoveStarted(SpriteMoveAnimation animation); void onNewSpriteMoveFrame(SpriteMoveAnimation animation); diff --git a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java index 60b6614aa..50b67a759 100644 --- a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java +++ b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java @@ -9,12 +9,8 @@ import java.util.List; public final class VisualEffectFrameListeners extends ListOfListeners implements VisualEffectFrameListener { - private final Function3 onNewAnimationFrame = new Function3() { - @Override public void call(VisualEffectFrameListener listener, VisualEffectAnimation animation, Integer tileID, Integer textYOffset) { listener.onNewAnimationFrame(animation, tileID, textYOffset); } - }; - - private final Function3, List, List> onNewAnimationFrames = new Function3, List, List>() { - @Override public void call(VisualEffectFrameListener listener, List animations, List tileIDs, List textYOffsets) { listener.onNewAnimationFrames(animations, tileIDs, textYOffsets); } + private final Function1> onNewAnimationFrames = new Function1>() { + @Override public void call(VisualEffectFrameListener listener, List effects) { listener.onNewAnimationFrames(effects); } }; private final Function1 onAnimationCompleted = new Function1() { @@ -36,15 +32,10 @@ public final class VisualEffectFrameListeners extends ListOfListeners onAsyncAreaUpdate = new Function1() { @Override public void call(VisualEffectFrameListener listener, CoordRect area) { listener.onAsyncAreaUpdate(area); } }; - - @Override - public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset) { - callAllListeners(this.onNewAnimationFrame, animation, tileID, textYOffset); - } @Override - public void onNewAnimationFrames(List animations, List tileIDs, List textYOffsets) { - callAllListeners(this.onNewAnimationFrames, animations, tileIDs, textYOffsets); + public void onNewAnimationFrames(List effects) { + callAllListeners(this.onNewAnimationFrames, effects); } @Override diff --git a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/view/MainView.java b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/view/MainView.java index 1e3adf451..5f57d51e0 100644 --- a/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/view/MainView.java +++ b/AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/view/MainView.java @@ -1,7 +1,6 @@ package com.gpl.rpg.AndorsTrail.view; import java.lang.ref.WeakReference; -import java.util.ArrayList; import java.util.List; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; @@ -10,7 +9,6 @@ import com.gpl.rpg.AndorsTrail.context.ControllerContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.controller.Constants; import com.gpl.rpg.AndorsTrail.controller.InputController; -import com.gpl.rpg.AndorsTrail.controller.VisualEffectController; import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.BloodSplatter; import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.SpriteMoveAnimation; import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation; @@ -32,7 +30,6 @@ 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; import android.content.Context; @@ -80,8 +77,6 @@ public final class MainView extends SurfaceView private final int[] debugColors = {Color.MAGENTA, Color.BLUE, Color.CYAN, Color.GREEN, Color.YELLOW, Color.RED, Color.WHITE}; private final CoordRect p1x1 = new CoordRect(new Coord(), new Size(1,1)); private boolean hasSurface = false; - - private List activeEffects = new ArrayList<>(); //DEBUG // private Coord touchedTile = null; @@ -164,8 +159,8 @@ public final class MainView extends SurfaceView // this.surfaceSize = new Size(w, h); this.surfaceSize = new Size((int) (getWidth() / scale), (int) (getHeight() / scale)); this.screenSizeTileCount = new Size( - (int) Math.floor(getWidth() / scaledTileSize) - ,(int) Math.floor(getHeight() / scaledTileSize) + getWidth() / scaledTileSize + ,getHeight() / scaledTileSize ); if (sh.getSurfaceFrame().right != surfaceSize.width || sh.getSurfaceFrame().bottom != surfaceSize.height) { @@ -232,28 +227,28 @@ public final class MainView extends SurfaceView if (scrolling && why != RedrawAllDebugReason.MapScrolling) return; if (!scrolling && movingSprites > 0 && why != RedrawAllDebugReason.SpriteMoved) return; } - redrawArea_(mapViewArea, null, 0, 0); + redrawArea_(mapViewArea, null); } private void redrawTile(final Coord p, RedrawTileDebugReason why) { if (scrolling) return; p1x1.topLeft.set(p); - redrawArea_(p1x1, null, 0, 0); + redrawArea_(p1x1, null); } private void redrawArea(final CoordRect area, RedrawAreaDebugReason why) { if (scrolling) return; - redrawArea_(area, null, 0, 0); + redrawArea_(area, null); } - private void redrawArea_(CoordRect area, final VisualEffectAnimation effect, int tileID, int textYOffset) { + private void redrawArea_(CoordRect area, final List effects) { if (!hasSurface) return; - + if (!currentMap.intersects(area)) return; if (!mapViewArea.intersects(area)) return; if (shouldRedrawEverything()) { area = mapViewArea; } - + calculateRedrawRect(area); redrawRect.intersect(redrawClip); Canvas c = null; @@ -269,69 +264,6 @@ public final class MainView extends SurfaceView if (area == mapViewArea) { area = adaptAreaToScrolling(area); } - - synchronized (holder) { synchronized (tiles) { - int xScroll = 0; - int yScroll = 0; - if (scrolling && scrollVector != null) { - xScroll = (int) (tileSize - (tileSize * (System.currentTimeMillis() - scrollStartTime) / SCROLL_DURATION)); - xScroll = Math.max(0, Math.min(tileSize, xScroll)) * scrollVector.x; - yScroll = (int) (tileSize - (tileSize * (System.currentTimeMillis() - scrollStartTime) / SCROLL_DURATION)); - yScroll = Math.max(0, Math.min(tileSize, yScroll)) * scrollVector.y; - } - c.clipRect(redrawClip); - c.translate(screenOffset.x + xScroll, screenOffset.y + yScroll); -// c.scale(scale, scale); - doDrawRect(c, area); - if (effect != null) { - drawFromMapPosition(c, area, effect.position, tileID); - if (effect.displayText != null) { - drawEffectText(c, area, effect, textYOffset, effect.getTextPaint()); - } - } - -// c.drawRect(new Rect( -// (area.topLeft.x - mapViewArea.topLeft.x) * tileSize, -// (area.topLeft.y - mapViewArea.topLeft.y) * tileSize, -// (area.topLeft.x - mapViewArea.topLeft.x + area.size.width) * tileSize - 1, -// (area.topLeft.y - mapViewArea.topLeft.y + area.size.height) * tileSize - 1), -// redrawHighlight); -// if (touchedTile != null) c.drawRect(new Rect( -// (touchedTile.x - mapViewArea.topLeft.x) * tileSize, -// (touchedTile.y - mapViewArea.topLeft.y) * tileSize, -// (touchedTile.x - mapViewArea.topLeft.x + 1) * tileSize - 1, -// (touchedTile.y - mapViewArea.topLeft.y + 1) * tileSize - 1), -// touchHighlight); - } } - } finally { - if (c != null) holder.unlockCanvasAndPost(c); - } - } - - private void redrawArea_(CoordRect area, final List effects, List tileIDs, List textYOffsets) { - if (!hasSurface) return; - - - if (!currentMap.intersects(area)) return; - if (!mapViewArea.intersects(area)) return; - - if (shouldRedrawEverything()) { - area = mapViewArea; - } - - calculateRedrawRect(area); - redrawRect.intersect(redrawClip); - Canvas c = null; - try { - c = holder.lockCanvas(redrawRect); - if (area != mapViewArea) { - if (isRedrawRectWholeScreen(redrawRect)) { - area = mapViewArea; - } - } - if (area == mapViewArea) { - area = adaptAreaToScrolling(area); - } synchronized (holder) { synchronized (tiles) { int xScroll = 0; @@ -345,29 +277,23 @@ public final class MainView extends SurfaceView c.clipRect(redrawClip); c.translate(screenOffset.x + xScroll, screenOffset.y + yScroll); doDrawRect(c, area); - // Render each effect - renderEffects(c); + renderEffects(c, effects); } } } finally { if (c != null) holder.unlockCanvasAndPost(c); } } - private void renderEffects(Canvas canvas) { - for (VisualEffectController.VisualEffectData data : activeEffects) { - VisualEffectAnimation effect = data.effect; - int tileID = data.tileID; - int textYOffset = data.textYOffset; - - L.log("Rendering effect at position: " + effect.position + " with tileID: " + tileID + " and textYOffset: " + textYOffset); - + private void renderEffects(Canvas canvas ,List effects) { + if(effects == null) return; + for (VisualEffectAnimation effect : effects) { + int tileID = effect.tileID; + int textYOffset = effect.textYOffset; drawFromMapPosition(canvas, effect.area, effect.position, tileID); if (effect.displayText != null) { drawEffectText(canvas, effect.area, effect, textYOffset, effect.getTextPaint()); } } - L.log("Total effects rendered: " + activeEffects.size()); - activeEffects.clear(); } private boolean isRedrawRectWholeScreen(Rect redrawRect) { @@ -385,16 +311,10 @@ public final class MainView extends SurfaceView return true; } private final Rect redrawRect = new Rect(); - private void redrawAreaWithEffect(final VisualEffectAnimation effect, int tileID, int textYOffset) { - CoordRect area = effect.area; -// if (shouldRedrawEverythingForVisualEffect()) area = mapViewArea; - redrawArea_(area, effect, tileID, textYOffset); - } - private void redrawAreaWithEffect(List effects, List tileIDs, List textYOffsets) { + private void redrawAreaWithEffect(List effects) { CoordRect area = null; for (int i = 0; i < effects.size(); i++) { VisualEffectAnimation effect = effects.get(i); - activeEffects.add(new VisualEffectController.VisualEffectData(effect, tileIDs.get(i), textYOffsets.get(i))); if (area == null) { area = effect.area; } else { @@ -402,7 +322,7 @@ public final class MainView extends SurfaceView } } if (area != null) { - redrawArea_(area, effects, tileIDs, textYOffsets); + redrawArea_(area, effects); } } @@ -878,14 +798,8 @@ public final class MainView extends SurfaceView } @Override - public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset) { - redrawAreaWithEffect(animation, tileID, textYOffset); - } - - @Override - public void onNewAnimationFrames(List animations, List tileIDs, List textYOffsets) { - L.log("Rendering " + animations.size() + " effects"); - redrawAreaWithEffect(animations, tileIDs, textYOffsets); + public void onNewAnimationFrames(List effects) { + redrawAreaWithEffect(effects); } @Override