Fix visual Bugs & slowdowns

This commit is contained in:
OMGeeky
2024-09-07 14:32:00 +02:00
parent bac004ae33
commit af3109b9d9
4 changed files with 75 additions and 79 deletions

View File

@@ -26,13 +26,18 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public final class VisualEffectController { public final class VisualEffectController {
private static final long EFFECT_UPDATE_INTERVAL = 25;
private int effectCount = 0; private int effectCount = 0;
private final List<VisualEffectAnimation> activeAnimations = new ArrayList<>();
private final ControllerContext controllers; private final ControllerContext controllers;
private final WorldContext world; private final WorldContext world;
private final VisualEffectCollection effectTypes; private final VisualEffectCollection effectTypes;
private final Handler animationHandler = new Handler();
private final List<VisualEffectAnimation> activeAnimations = new ArrayList<>();
public final VisualEffectFrameListeners visualEffectFrameListeners = new VisualEffectFrameListeners(); 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) { public VisualEffectController(ControllerContext controllers, WorldContext world) {
this.controllers = controllers; 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) { public void startEffect(Coord position, VisualEffectCollection.VisualEffectID effectID, String displayValue, VisualEffectCompletedCallback callback, int callbackValue) {
++effectCount; ++effectCount;
VisualEffectAnimation animation = new VisualEffectAnimation(effectTypes.getVisualEffect(effectID), position, displayValue, callback, callbackValue); VisualEffectAnimation animation = new VisualEffectAnimation(effectTypes.getVisualEffect(effectID), position, displayValue, callback, callbackValue);
activeAnimations.add(animation);
animation.start(); animation.start();
} }
public void collectAndSendAnimations(VisualEffectAnimation animation) { private void startAnimation(VisualEffectAnimation animation) {
List<Integer> tileIDs = new ArrayList<>(); activeAnimations.add(animation);
List<Integer> yOffsets = new ArrayList<>(); animation.update();
//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 if (activeAnimations.size() == 1) {
//TODO: if someone got time to make this look nice, be my guest animationHandler.postDelayed(animationRunnable, 0);
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);
} }
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 VisualEffectCollection.VisualEffectID enqueuedEffectID = null;
private int enqueuedEffectValue = 0; private int enqueuedEffectValue = 0;
public void enqueueEffect(VisualEffectCollection.VisualEffectID effectID, int displayValue) { public void enqueueEffect(VisualEffectCollection.VisualEffectID effectID, int displayValue) {
@@ -85,8 +106,8 @@ public final class VisualEffectController {
.start(); .start();
} }
public final class SpriteMoveAnimation extends Handler implements Runnable { public final class SpriteMoveAnimation implements Runnable {
private final Handler handler = new Handler();
// private static final int millisecondsPerFrame=25; // private static final int millisecondsPerFrame=25;
private final VisualEffectCompletedCallback callback; private final VisualEffectCompletedCallback callback;
@@ -140,7 +161,7 @@ public final class VisualEffectController {
visualEffectFrameListeners.onSpriteMoveStarted(this); visualEffectFrameListeners.onSpriteMoveStarted(this);
if (duration == 0 || !controllers.preferences.enableUiAnimations) onCompleted(); if (duration == 0 || !controllers.preferences.enableUiAnimations) onCompleted();
else { else {
postDelayed(this, duration); handler.postDelayed(this, duration);
} }
} }
@@ -155,58 +176,41 @@ public final class VisualEffectController {
textPaint.setTextAlign(Align.CENTER); textPaint.setTextAlign(Align.CENTER);
} }
public static class VisualEffectData { public final class VisualEffectAnimation {
public final VisualEffectAnimation effect; public int tileID;
public final int tileID; public int textYOffset;
public final int textYOffset; public long durationPassed = 0;
public VisualEffectData(VisualEffectAnimation effect, int tileID, int textYOffset) { private void updateFrame() {
this.effect = effect; long frameDuration = (long) effect.millisecondPerFrame * controllers.preferences.attackspeed_milliseconds / AndorsTrailPreferences.ATTACKSPEED_DEFAULT_MILLISECONDS;
this.tileID = tileID; while (durationPassed > frameDuration) {
this.textYOffset = textYOffset; currentFrame++;
} durationPassed -= frameDuration;
}
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 update() { private void update() {
++currentFrame; if (currentFrame >= effect.lastFrame) {
int frame = currentFrame; return;
}
// int tileID = effect.frameIconIDs[frame]; tileID = effect.frameIconIDs[currentFrame];
// int textYOffset = -2 * (frame); textYOffset = -2 * (currentFrame);
if (frame >= beginFadeAtFrame && displayText != null) { if (currentFrame >= beginFadeAtFrame && displayText != null) {
textPaint.setAlpha(255 * (effect.lastFrame - frame) / (effect.lastFrame - beginFadeAtFrame)); textPaint.setAlpha(255 * (effect.lastFrame - currentFrame) / (effect.lastFrame - beginFadeAtFrame));
} }
area.topLeft.y = position.y - 1; 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() { private void onCompleted() {
--effectCount;
activeAnimations.remove(this);
visualEffectFrameListeners.onAnimationCompleted(this); visualEffectFrameListeners.onAnimationCompleted(this);
if (callback != null) callback.onVisualEffectCompleted(callbackValue); if (callback != null) callback.onVisualEffectCompleted(callbackValue);
} }
public void start() { public void start() {
if (!controllers.preferences.enableUiAnimations) onCompleted(); if (!controllers.preferences.enableUiAnimations) onCompleted();
else postDelayed(this, 0); else startAnimation(this);
} }
private int currentFrame = 0; private int currentFrame = 0;
@@ -235,7 +239,7 @@ public final class VisualEffectController {
this.area = new CoordRect(new Coord(position.x - (widthNeededInTiles / 2), position.y - 1), new Size(widthNeededInTiles, 2)); this.area = new CoordRect(new Coord(position.x - (widthNeededInTiles / 2), position.y - 1), new Size(widthNeededInTiles, 2));
this.beginFadeAtFrame = effect.lastFrame / 2; this.beginFadeAtFrame = effect.lastFrame / 2;
} }
public Paint getTextPaint(){ public Paint getTextPaint(){
return textPaint; return textPaint;
} }

View File

@@ -8,7 +8,7 @@ import java.util.List;
public interface VisualEffectFrameListener { public interface VisualEffectFrameListener {
void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset); void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset);
void onNewAnimationFrames(List<VisualEffectAnimation> animations, List<Integer> tileIDs, List<Integer> textYOffsets); void onNewAnimationFrames(List<VisualEffectAnimation> effects);
void onAnimationCompleted(VisualEffectAnimation animation); void onAnimationCompleted(VisualEffectAnimation animation);
void onSpriteMoveStarted(SpriteMoveAnimation animation); void onSpriteMoveStarted(SpriteMoveAnimation animation);
void onNewSpriteMoveFrame(SpriteMoveAnimation animation); void onNewSpriteMoveFrame(SpriteMoveAnimation animation);

View File

@@ -1,5 +1,6 @@
package com.gpl.rpg.AndorsTrail.controller.listeners; package com.gpl.rpg.AndorsTrail.controller.listeners;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.SpriteMoveAnimation; import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.SpriteMoveAnimation;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation; import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation;
import com.gpl.rpg.AndorsTrail.util.CoordRect; import com.gpl.rpg.AndorsTrail.util.CoordRect;
@@ -13,8 +14,8 @@ public final class VisualEffectFrameListeners extends ListOfListeners<VisualEffe
@Override public void call(VisualEffectFrameListener listener, VisualEffectAnimation animation, Integer tileID, Integer textYOffset) { listener.onNewAnimationFrame(animation, tileID, textYOffset); } @Override public void call(VisualEffectFrameListener listener, VisualEffectAnimation animation, Integer tileID, Integer textYOffset) { listener.onNewAnimationFrame(animation, tileID, textYOffset); }
}; };
private final Function3<VisualEffectFrameListener, List<VisualEffectAnimation>, List<Integer>, List<Integer>> onNewAnimationFrames = new Function3<VisualEffectFrameListener, List<VisualEffectAnimation>, List<Integer>, List<Integer>>() { private final Function1<VisualEffectFrameListener, List<VisualEffectAnimation>> onNewAnimationFrames = new Function1<VisualEffectFrameListener, List<VisualEffectAnimation>>() {
@Override public void call(VisualEffectFrameListener listener, List<VisualEffectAnimation> animations, List<Integer> tileIDs, List<Integer> textYOffsets) { listener.onNewAnimationFrames(animations, tileIDs, textYOffsets); } @Override public void call(VisualEffectFrameListener listener, List<VisualEffectAnimation> effects) { listener.onNewAnimationFrames(effects); }
}; };
private final Function1<VisualEffectFrameListener, VisualEffectAnimation> onAnimationCompleted = new Function1<VisualEffectFrameListener, VisualEffectAnimation>() { private final Function1<VisualEffectFrameListener, VisualEffectAnimation> onAnimationCompleted = new Function1<VisualEffectFrameListener, VisualEffectAnimation>() {
@@ -43,8 +44,8 @@ public final class VisualEffectFrameListeners extends ListOfListeners<VisualEffe
} }
@Override @Override
public void onNewAnimationFrames(List<VisualEffectAnimation> animations, List<Integer> tileIDs, List<Integer> textYOffsets) { public void onNewAnimationFrames(List<VisualEffectAnimation> effects) {
callAllListeners(this.onNewAnimationFrames, animations, tileIDs, textYOffsets); callAllListeners(this.onNewAnimationFrames, effects);
} }
@Override @Override

View File

@@ -81,7 +81,6 @@ public final class MainView extends SurfaceView
private final CoordRect p1x1 = new CoordRect(new Coord(), new Size(1,1)); private final CoordRect p1x1 = new CoordRect(new Coord(), new Size(1,1));
private boolean hasSurface = false; private boolean hasSurface = false;
private List<VisualEffectController.VisualEffectData> activeEffects = new ArrayList<>();
//DEBUG //DEBUG
// private Coord touchedTile = null; // private Coord touchedTile = null;
@@ -164,8 +163,8 @@ public final class MainView extends SurfaceView
// this.surfaceSize = new Size(w, h); // this.surfaceSize = new Size(w, h);
this.surfaceSize = new Size((int) (getWidth() / scale), (int) (getHeight() / scale)); this.surfaceSize = new Size((int) (getWidth() / scale), (int) (getHeight() / scale));
this.screenSizeTileCount = new Size( this.screenSizeTileCount = new Size(
(int) Math.floor(getWidth() / scaledTileSize) getWidth() / scaledTileSize
,(int) Math.floor(getHeight() / scaledTileSize) ,getHeight() / scaledTileSize
); );
if (sh.getSurfaceFrame().right != surfaceSize.width || sh.getSurfaceFrame().bottom != surfaceSize.height) { if (sh.getSurfaceFrame().right != surfaceSize.width || sh.getSurfaceFrame().bottom != surfaceSize.height) {
@@ -308,7 +307,7 @@ public final class MainView extends SurfaceView
} }
} }
private void redrawArea_(CoordRect area, final List<VisualEffectAnimation> effects, List<Integer> tileIDs, List<Integer> textYOffsets) { private void redrawArea_(CoordRect area, final List<VisualEffectAnimation> effects) {
if (!hasSurface) return; if (!hasSurface) return;
@@ -346,28 +345,22 @@ public final class MainView extends SurfaceView
c.translate(screenOffset.x + xScroll, screenOffset.y + yScroll); c.translate(screenOffset.x + xScroll, screenOffset.y + yScroll);
doDrawRect(c, area); doDrawRect(c, area);
// Render each effect // Render each effect
renderEffects(c); renderEffects(c, effects);
} } } }
} finally { } finally {
if (c != null) holder.unlockCanvasAndPost(c); if (c != null) holder.unlockCanvasAndPost(c);
} }
} }
private void renderEffects(Canvas canvas) { private void renderEffects(Canvas canvas ,List<VisualEffectAnimation> effects) {
for (VisualEffectController.VisualEffectData data : activeEffects) { for (VisualEffectAnimation effect : effects) {
VisualEffectAnimation effect = data.effect; int tileID = effect.tileID;
int tileID = data.tileID; int textYOffset = effect.textYOffset;
int textYOffset = data.textYOffset;
L.log("Rendering effect at position: " + effect.position + " with tileID: " + tileID + " and textYOffset: " + textYOffset);
drawFromMapPosition(canvas, effect.area, effect.position, tileID); drawFromMapPosition(canvas, effect.area, effect.position, tileID);
if (effect.displayText != null) { if (effect.displayText != null) {
drawEffectText(canvas, effect.area, effect, textYOffset, effect.getTextPaint()); drawEffectText(canvas, effect.area, effect, textYOffset, effect.getTextPaint());
} }
} }
L.log("Total effects rendered: " + activeEffects.size());
activeEffects.clear();
} }
private boolean isRedrawRectWholeScreen(Rect redrawRect) { private boolean isRedrawRectWholeScreen(Rect redrawRect) {
@@ -390,11 +383,10 @@ public final class MainView extends SurfaceView
// if (shouldRedrawEverythingForVisualEffect()) area = mapViewArea; // if (shouldRedrawEverythingForVisualEffect()) area = mapViewArea;
redrawArea_(area, effect, tileID, textYOffset); redrawArea_(area, effect, tileID, textYOffset);
} }
private void redrawAreaWithEffect(List<VisualEffectAnimation> effects, List<Integer> tileIDs, List<Integer> textYOffsets) { private void redrawAreaWithEffect(List<VisualEffectAnimation> effects) {
CoordRect area = null; CoordRect area = null;
for (int i = 0; i < effects.size(); i++) { for (int i = 0; i < effects.size(); i++) {
VisualEffectAnimation effect = effects.get(i); VisualEffectAnimation effect = effects.get(i);
activeEffects.add(new VisualEffectController.VisualEffectData(effect, tileIDs.get(i), textYOffsets.get(i)));
if (area == null) { if (area == null) {
area = effect.area; area = effect.area;
} else { } else {
@@ -402,7 +394,7 @@ public final class MainView extends SurfaceView
} }
} }
if (area != null) { if (area != null) {
redrawArea_(area, effects, tileIDs, textYOffsets); redrawArea_(area, effects);
} }
} }
@@ -878,14 +870,13 @@ public final class MainView extends SurfaceView
} }
@Override @Override
public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset) { public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset){
redrawAreaWithEffect(animation, tileID, textYOffset); redrawAreaWithEffect(animation, tileID, textYOffset);
} }
@Override @Override
public void onNewAnimationFrames(List<VisualEffectAnimation> animations, List<Integer> tileIDs, List<Integer> textYOffsets) { public void onNewAnimationFrames(List<VisualEffectAnimation> effects) {
L.log("Rendering " + animations.size() + " effects"); redrawAreaWithEffect(effects);
redrawAreaWithEffect(animations, tileIDs, textYOffsets);
} }
@Override @Override