diff --git a/packages/pinball_components/lib/src/components/plunger.dart b/packages/pinball_components/lib/src/components/plunger.dart index 79b370a0..040c3287 100644 --- a/packages/pinball_components/lib/src/components/plunger.dart +++ b/packages/pinball_components/lib/src/components/plunger.dart @@ -97,7 +97,7 @@ class Plunger extends BodyComponent with InitialPosition, Layered, ZIndex { void update(double dt) { // Ensure that we only pull or release when the time is greater than zero. if (_pullingDownTime > 0) { - _pullingDownTime -= dt; + _pullingDownTime -= PinballForge2DGame.clampDt(dt); if (_pullingDownTime <= 0) { release(); } else { diff --git a/packages/pinball_components/test/src/components/plunger_test.dart b/packages/pinball_components/test/src/components/plunger_test.dart index abb42d68..fd759f8d 100644 --- a/packages/pinball_components/test/src/components/plunger_test.dart +++ b/packages/pinball_components/test/src/components/plunger_test.dart @@ -141,7 +141,11 @@ void main() { expect(plunger.body.linearVelocity.y, isPositive); - await tester.pump(const Duration(seconds: 2)); + // Call game update at 120 FPS, so that the plunger will act as if it + // was pulled for 2 seconds. + for (var i = 0.0; i < 2; i += 1 / 120) { + game.update(1 / 20); + } expect(plunger.body.linearVelocity.y, isZero); }, diff --git a/packages/pinball_flame/lib/src/pinball_forge2d_game.dart b/packages/pinball_flame/lib/src/pinball_forge2d_game.dart index 118baad9..0013dd26 100644 --- a/packages/pinball_flame/lib/src/pinball_forge2d_game.dart +++ b/packages/pinball_flame/lib/src/pinball_forge2d_game.dart @@ -24,7 +24,7 @@ class PinballForge2DGame extends FlameGame implements Forge2DGame { @override void update(double dt) { super.update(dt); - world.stepDt(min(dt, 1 / 60)); + world.stepDt(clampDt(dt)); } @override @@ -41,4 +41,14 @@ class PinballForge2DGame extends FlameGame implements Forge2DGame { Vector2 worldToScreen(Vector2 position) { throw UnimplementedError(); } + + /// Clamp the [dt] in such a way that it would never exceed the minimal of + /// 1/60th of a second. + /// + /// Note: this is a static method because composing this class as a generic + /// on `BodyComponent` and mixins for that class will crash the Dart analyzer + /// server. + static double clampDt(double dt) { + return min(dt, 1 / 60); + } } diff --git a/packages/pinball_flame/test/src/pinball_forge2d_game_test.dart b/packages/pinball_flame/test/src/pinball_forge2d_game_test.dart index 872f8b97..b8dc9fcc 100644 --- a/packages/pinball_flame/test/src/pinball_forge2d_game_test.dart +++ b/packages/pinball_flame/test/src/pinball_forge2d_game_test.dart @@ -47,5 +47,17 @@ void main() { ); }, ); + + group('clampDt', () { + test('returns dt', () { + const dt = 0.0001; + expect(PinballForge2DGame.clampDt(dt), equals(dt)); + }); + + test('returns result of 1/60 as dt is to high', () { + const dt = 1.0; + expect(PinballForge2DGame.clampDt(dt), equals(1 / 60)); + }); + }); }); }