diff --git a/lib/effects/effects.dart b/lib/effects/effects.dart index af110d19b..e288da6c7 100644 --- a/lib/effects/effects.dart +++ b/lib/effects/effects.dart @@ -67,6 +67,7 @@ abstract class ComponentEffect { currentTime = currentTime.clamp(0.0, peakTime).toDouble(); if (hasFinished()) { onComplete?.call(); + _setComponentToEndState(); } } } @@ -108,6 +109,8 @@ abstract class ComponentEffect { driftTime = 0; } } + + void _setComponentToEndState(); } abstract class PositionComponentEffect @@ -141,16 +144,23 @@ abstract class PositionComponentEffect void initialize(PositionComponent component) { super.initialize(component); this.component = component; - originalPosition = component.position; + originalPosition = component.position.clone(); originalAngle = component.angle; - originalSize = component.size; + originalSize = component.size.clone(); /// If these aren't modified by the extending effect it is assumed that the /// effect didn't bring the component to another state than the one it /// started in - endPosition = component.position; + endPosition = component.position.clone(); endAngle = component.angle; - endSize = component.size; + endSize = component.size.clone(); + } + + @override + void _setComponentToEndState() { + component.position.setFrom(endPosition); + component.angle = endAngle; + component.size.setFrom(endSize); } } diff --git a/lib/effects/move_effect.dart b/lib/effects/move_effect.dart index f190a67d7..17c022e5c 100644 --- a/lib/effects/move_effect.dart +++ b/lib/effects/move_effect.dart @@ -66,11 +66,7 @@ class MoveEffect extends SimplePositionComponentEffect { } else { _movePath = path; } - if (!isAlternating) { - endPosition = _movePath.last; - } else { - endPosition = _startPosition; - } + endPosition = isAlternating ? _startPosition : _movePath.last; double pathLength = 0; Vector2 lastPosition = _startPosition; @@ -113,16 +109,19 @@ class MoveEffect extends SimplePositionComponentEffect { @override void update(double dt) { super.update(dt); - _currentSubPath ??= _percentagePath.first; - if (!curveDirection.isNegative && _currentSubPath.endAt < curveProgress || - curveDirection.isNegative && _currentSubPath.startAt > curveProgress) { - _currentSubPath = - _percentagePath.firstWhere((v) => v.endAt >= curveProgress); + if (!hasFinished()) { + _currentSubPath ??= _percentagePath.first; + if (!curveDirection.isNegative && _currentSubPath.endAt < curveProgress || + curveDirection.isNegative && + _currentSubPath.startAt > curveProgress) { + _currentSubPath = + _percentagePath.firstWhere((v) => v.endAt >= curveProgress); + } + final double lastEndAt = _currentSubPath.startAt; + final double localPercentage = + (curveProgress - lastEndAt) / (_currentSubPath.endAt - lastEndAt); + component.position = _currentSubPath.previous + + ((_currentSubPath.v - _currentSubPath.previous) * localPercentage); } - final double lastEndAt = _currentSubPath.startAt; - final double localPercentage = - (curveProgress - lastEndAt) / (_currentSubPath.endAt - lastEndAt); - component.position = _currentSubPath.previous + - ((_currentSubPath.v - _currentSubPath.previous) * localPercentage); } } diff --git a/lib/effects/rotate_effect.dart b/lib/effects/rotate_effect.dart index 141d1299e..18811619a 100644 --- a/lib/effects/rotate_effect.dart +++ b/lib/effects/rotate_effect.dart @@ -34,19 +34,21 @@ class RotateEffect extends SimplePositionComponentEffect { @override void initialize(_comp) { super.initialize(_comp); - if (!isAlternating) { - endAngle = _comp.angle + angle; - } _startAngle = component.angle; _delta = isRelative ? angle : angle - _startAngle; + if (!isAlternating) { + endAngle = _startAngle + _delta; + } speed ??= _delta / duration; duration ??= _delta / speed; - peakTime = duration; + peakTime = isAlternating ? duration / 2 : duration; } @override void update(double dt) { super.update(dt); - component.angle = _startAngle + _delta * curveProgress; + if (!hasFinished()) { + component.angle = _startAngle + _delta * curveProgress; + } } } diff --git a/lib/effects/scale_effect.dart b/lib/effects/scale_effect.dart index b12eac53d..054445efb 100644 --- a/lib/effects/scale_effect.dart +++ b/lib/effects/scale_effect.dart @@ -35,19 +35,21 @@ class ScaleEffect extends SimplePositionComponentEffect { @override void initialize(_comp) { super.initialize(_comp); - if (!isAlternating) { - endSize = size.clone(); - } _startSize = component.size; _delta = isRelative ? size : size - _startSize; + if (!isAlternating) { + endSize = _startSize + _delta; + } speed ??= _delta.length / duration; duration ??= _delta.length / speed; - peakTime = duration; + peakTime = isAlternating ? duration / 2 : duration; } @override void update(double dt) { super.update(dt); - component.size = _startSize + _delta * curveProgress; + if (!hasFinished()) { + component.size = _startSize + _delta * curveProgress; + } } } diff --git a/test/effects/effect_test_utils.dart b/test/effects/effect_test_utils.dart index dbed9a5ec..6ddd3605f 100644 --- a/test/effects/effect_test_utils.dart +++ b/test/effects/effect_test_utils.dart @@ -18,7 +18,7 @@ void effectTest( WidgetTester tester, PositionComponent component, PositionComponentEffect effect, { - bool hasFinished = true, + bool shouldFinish = true, double iterations = 1.0, double expectedAngle = 0.0, Vector2 expectedPosition, @@ -41,25 +41,51 @@ void effectTest( game.update(stepDelta); timeLeft -= stepDelta; } - expect( - effect.hasFinished(), - hasFinished, - reason: "Effect.hasFinished() didn't have the expected value", - ); - expect( - callback.isCalled, - hasFinished, - reason: 'Callback was not treated properly', - ); - expect( - component.position, - expectedPosition, - reason: "Position is not correct", - ); - expect(component.angle, expectedAngle, reason: "Angle is not correct"); - expect(component.size, expectedSize, reason: "Size is not correct"); + expect(effect.hasFinished(), shouldFinish, reason: "Effect shouldFinish"); + expect(callback.isCalled, shouldFinish, reason: "Callback was treated wrong"); + if (!shouldFinish) { + const double floatRange = 0.001; + bool acceptableVector(Vector2 vector, Vector2 expectedVector) { + return (expectedVector - vector).length < floatRange; + } + + final bool acceptablePosition = + acceptableVector(component.position, expectedPosition); + final bool acceptableSize = acceptableVector(component.size, expectedSize); + final bool acceptableAngle = + (expectedAngle - component.angle).abs() < floatRange; + assert( + acceptablePosition, + "Position is not correct (${component.position} vs $expectedPosition)", + ); + assert( + acceptableAngle, + "Angle is not correct (${component.angle} vs $expectedAngle)", + ); + assert( + acceptableSize, + "Size is not correct (${component.size} vs $expectedSize)", + ); + } else { + //game.update(0.1); + expect( + component.position, + expectedPosition, + reason: "Position is not exactly correct", + ); + expect( + component.angle, + expectedAngle, + reason: "Angle is not exactly correct", + ); + expect( + component.size, + expectedSize, + reason: "Size is not exactly correct", + ); + } game.update(0.0); // Since effects are removed before they are updated - expect(component.effects.isEmpty, hasFinished); + expect(component.effects.isEmpty, shouldFinish); } class Square extends PositionComponent { diff --git a/test/effects/move_effect_test.dart b/test/effects/move_effect_test.dart index 7fba1314c..10c66e285 100644 --- a/test/effects/move_effect_test.dart +++ b/test/effects/move_effect_test.dart @@ -68,7 +68,7 @@ void main() { moveEffect, expectedPosition: positionComponent.position.clone(), iterations: 1.0, - hasFinished: false, + shouldFinish: false, ); }, ); @@ -81,7 +81,7 @@ void main() { positionComponent, moveEffect, expectedPosition: path.last, - hasFinished: false, + shouldFinish: false, iterations: 0.5, ); }); @@ -95,7 +95,7 @@ void main() { moveEffect, expectedPosition: path.last, iterations: 3.0, - hasFinished: false, + shouldFinish: false, ); }); } diff --git a/test/effects/rotate_effect_test.dart b/test/effects/rotate_effect_test.dart index c9078e32d..527109468 100644 --- a/test/effects/rotate_effect_test.dart +++ b/test/effects/rotate_effect_test.dart @@ -73,7 +73,7 @@ void main() { rotateEffect, expectedAngle: positionComponent.angle, iterations: 1.0, - hasFinished: false, + shouldFinish: false, ); }, ); @@ -86,7 +86,7 @@ void main() { positionComponent, rotateEffect, expectedAngle: angleArgument, - hasFinished: false, + shouldFinish: false, iterations: 0.5, ); }); @@ -100,7 +100,7 @@ void main() { rotateEffect, expectedAngle: angleArgument, iterations: 3.0, - hasFinished: false, + shouldFinish: false, ); }); } diff --git a/test/effects/scale_effect_test.dart b/test/effects/scale_effect_test.dart index 41c221133..697d0d32e 100644 --- a/test/effects/scale_effect_test.dart +++ b/test/effects/scale_effect_test.dart @@ -68,7 +68,7 @@ void main() { scaleEffect, expectedSize: positionComponent.size.clone(), iterations: 1.0, - hasFinished: false, + shouldFinish: false, ); }, ); @@ -81,7 +81,7 @@ void main() { positionComponent, scaleEffect, expectedSize: argumentSize, - hasFinished: false, + shouldFinish: false, iterations: 0.5, ); }); @@ -95,7 +95,7 @@ void main() { scaleEffect, expectedSize: argumentSize, iterations: 3.0, - hasFinished: false, + shouldFinish: false, ); }); }