diff --git a/lib/game/components/game_bloc_status_listener.dart b/lib/game/components/game_bloc_status_listener.dart index 3e2d6581..8a30da45 100644 --- a/lib/game/components/game_bloc_status_listener.dart +++ b/lib/game/components/game_bloc_status_listener.dart @@ -5,6 +5,7 @@ import 'package:pinball/select_character/select_character.dart'; import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; +import 'package:platform_helper/platform_helper.dart'; /// Listens to the [GameBloc] and updates the game accordingly. class GameBlocStatusListener extends Component @@ -53,11 +54,36 @@ class GameBlocStatusListener extends Component } } - void _addPlungerKeyControls(Plunger plunger) => - plunger.add(PlungerKeyControllingBehavior()); + void _addPlungerKeyControls(Plunger plunger) { + final platformHelper = readProvider(); + const pullingStrength = 7.0; + final provider = + plunger.firstChild>()!; - void _removePlungerKeyControls(Plunger plunger) => - plunger.remove(PlungerKeyControllingBehavior()); + if (platformHelper.isMobile) { + provider.add( + PlungerAutoPullingBehavior(strength: pullingStrength), + ); + } else { + provider.addAll( + [ + PlungerKeyControllingBehavior(), + PlungerPullingBehavior(strength: 7), + ], + ); + } + } + + void _removePlungerKeyControls(Plunger plunger) { + plunger + .descendants() + .whereType() + .forEach(plunger.remove); + plunger + .descendants() + .whereType() + .forEach(plunger.remove); + } void _addFlipperKeyControls(Flipper flipper) => flipper ..add(FlipperKeyControllingBehavior()) diff --git a/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart b/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart index fdbd40f2..fcff816a 100644 --- a/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart +++ b/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart @@ -6,7 +6,7 @@ import 'package:pinball_components/pinball_components.dart'; /// Allows controlling the [Plunger]'s movement with keyboard input. class PlungerKeyControllingBehavior extends Component with KeyboardHandler, FlameBlocReader { - /// The [LogicalKeyboardKey]s that will control the [Flipper]. + /// The [LogicalKeyboardKey]s that will control the [Plunger]. /// /// [onKeyEvent] method listens to when one of these keys is pressed. static const List _keys = [ diff --git a/packages/pinball_components/lib/src/components/plunger/plunger.dart b/packages/pinball_components/lib/src/components/plunger/plunger.dart index 63c81cff..9f3b6873 100644 --- a/packages/pinball_components/lib/src/components/plunger/plunger.dart +++ b/packages/pinball_components/lib/src/components/plunger/plunger.dart @@ -24,8 +24,8 @@ class Plunger extends BodyComponent with InitialPosition, Layered, ZIndex { create: PlungerCubit.new, children: [ _PlungerSpriteAnimationGroupComponent(), - PlungerPullingBehavior(strength: 7), PlungerReleasingBehavior(strength: 11), + PlungerNoiseBehavior(), ], ), PlungerJointingBehavior(compressionDistance: 9.2), diff --git a/packages/pinball_components/test/src/components/plunger/plunger_test.dart b/packages/pinball_components/test/src/components/plunger/plunger_test.dart index f4b5c446..32a6a45b 100644 --- a/packages/pinball_components/test/src/components/plunger/plunger_test.dart +++ b/packages/pinball_components/test/src/components/plunger/plunger_test.dart @@ -26,6 +26,44 @@ void main() { }, ); + group('adds', () { + flameTester.test( + 'a PlungerReleasingBehavior', + (game) async { + final plunger = Plunger(); + await game.ensureAdd(plunger); + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); + + flameTester.test( + 'a PlungerJointingBehavior', + (game) async { + final plunger = Plunger(); + await game.ensureAdd(plunger); + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); + + flameTester.test( + 'a PlungerNoiseBehavior', + (game) async { + final plunger = Plunger(); + await game.ensureAdd(plunger); + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); + }); + group('renders correctly', () { const goldenPath = '../golden/plunger/'; flameTester.testGameWidget( @@ -74,30 +112,5 @@ void main() { }, ); }); - - // group('body', () { - // test('is dynamic', () { - // final body = Plunger.test().createBody(); - // expect(body.bodyType, equals(BodyType.dynamic)); - // }); - - // test('ignores gravity', () { - // final body = Plunger().createBody(); - // expect(body.gravityScale, equals(Vector2.zero())); - // }); - // }); - - // group('fixture', () { - // test('exists', () async { - // final body = Plunger().createBody(); - // expect(body.fixtures[0], isA()); - // }); - - // test('has density', () { - // final body = Plunger().createBody(); - // final fixture = body.fixtures[0]; - // expect(fixture.density, greaterThan(0)); - // }); - // }); }); } diff --git a/test/game/components/game_bloc_status_listener_test.dart b/test/game/components/game_bloc_status_listener_test.dart index 7d0a6c6b..3519dbbd 100644 --- a/test/game/components/game_bloc_status_listener_test.dart +++ b/test/game/components/game_bloc_status_listener_test.dart @@ -36,6 +36,7 @@ class _TestGame extends Forge2DGame with HasTappables { Future pump( Iterable children, { PinballAudioPlayer? pinballAudioPlayer, + PlatformHelper? platformHelper, }) async { return ensureAdd( FlameMultiBlocProvider( @@ -57,7 +58,7 @@ class _TestGame extends Forge2DGame with HasTappables { _MockAppLocalizations(), ), FlameProvider.value( - _MockPlatformHelper(), + platformHelper ?? PlatformHelper(), ), ], children: children, @@ -75,10 +76,9 @@ class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { class _MockShareRepository extends Mock implements ShareRepository {} -class _MockPlatformHelper extends Mock implements PlatformHelper { - @override - bool get isMobile => false; -} +class _MockPlatformHelper extends Mock implements PlatformHelper {} + +class _MockPlungerCubit extends Mock implements PlungerCubit {} class _MockAppLocalizations extends Mock implements AppLocalizations { @override @@ -196,7 +196,6 @@ void main() { await flipper.ensureAdd(behavior); expect(state.status, GameStatus.gameOver); - component.onNewState(state); await game.ready(); @@ -219,13 +218,18 @@ void main() { entries: const [], ); final plunger = Plunger.test(); - final behavior = PlungerKeyControllingBehavior(); + await game.pump( + [component, backbox, plunger], + ); - await game.pump([component, backbox, plunger]); - await plunger.ensureAdd(behavior); + await plunger.ensureAdd( + FlameBlocProvider( + create: PlungerCubit.new, + children: [PlungerKeyControllingBehavior()], + ), + ); expect(state.status, GameStatus.gameOver); - component.onNewState(state); await game.ready(); @@ -236,6 +240,43 @@ void main() { }, ); + flameTester.test( + 'removes PlungerPullingBehavior from Plunger', + (game) async { + final component = GameBlocStatusListener(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); + final backbox = Backbox( + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, + entries: const [], + ); + final plunger = Plunger.test(); + await game.pump( + [component, backbox, plunger], + ); + + await plunger.ensureAdd( + FlameBlocProvider( + create: PlungerCubit.new, + children: [ + PlungerPullingBehavior(strength: 0), + PlungerAutoPullingBehavior(strength: 0) + ], + ), + ); + + expect(state.status, GameStatus.gameOver); + component.onNewState(state); + await game.ready(); + + expect( + plunger.children.whereType(), + isEmpty, + ); + }, + ); + flameTester.test( 'plays the game over voice over', (game) async { @@ -292,7 +333,7 @@ void main() { ); flameTester.test( - 'adds key controlling behavior to Flippers when the game is started', + 'adds FlipperKeyControllingBehavior to Flippers', (game) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); @@ -317,6 +358,120 @@ void main() { ); }, ); + + flameTester.test( + 'adds PlungerKeyControllingBehavior to Plunger when on desktop', + (game) async { + final platformHelper = _MockPlatformHelper(); + when(() => platformHelper.isMobile).thenReturn(false); + final component = GameBlocStatusListener(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); + final backbox = Backbox( + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, + entries: const [], + ); + final plunger = Plunger.test(); + await game.pump( + [component, backbox, plunger], + platformHelper: platformHelper, + ); + await plunger.ensureAdd( + FlameBlocProvider( + create: _MockPlungerCubit.new, + ), + ); + + expect(state.status, GameStatus.playing); + + component.onNewState(state); + await game.ready(); + + expect( + plunger + .descendants() + .whereType() + .length, + equals(1), + ); + }, + ); + + flameTester.test( + 'adds PlungerPullingBehavior to Plunger when on desktop', + (game) async { + final platformHelper = _MockPlatformHelper(); + when(() => platformHelper.isMobile).thenReturn(false); + final component = GameBlocStatusListener(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); + final backbox = Backbox( + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, + entries: const [], + ); + final plunger = Plunger.test(); + await game.pump( + [component, backbox, plunger], + platformHelper: platformHelper, + ); + await plunger.ensureAdd( + FlameBlocProvider( + create: _MockPlungerCubit.new, + ), + ); + + expect(state.status, GameStatus.playing); + + component.onNewState(state); + await game.ready(); + + expect( + plunger.descendants().whereType().length, + equals(1), + ); + }, + ); + + flameTester.test( + 'adds PlungerAutoPullingBehavior to Plunger when on mobile', + (game) async { + final platformHelper = _MockPlatformHelper(); + when(() => platformHelper.isMobile).thenReturn(true); + final component = GameBlocStatusListener(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); + final backbox = Backbox( + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, + entries: const [], + ); + final plunger = Plunger.test(); + await game.pump( + [component, backbox, plunger], + platformHelper: platformHelper, + ); + await plunger.ensureAdd( + FlameBlocProvider( + create: _MockPlungerCubit.new, + ), + ); + + expect(state.status, GameStatus.playing); + + component.onNewState(state); + await game.ready(); + + expect( + plunger + .descendants() + .whereType() + .length, + equals(1), + ); + }, + ); }); }); });