diff --git a/lib/game/bloc/game_bloc.dart b/lib/game/bloc/game_bloc.dart index 12941315..669d09e4 100644 --- a/lib/game/bloc/game_bloc.dart +++ b/lib/game/bloc/game_bloc.dart @@ -10,6 +10,7 @@ part 'game_state.dart'; class GameBloc extends Bloc { GameBloc() : super(const GameState.initial()) { on(_onBallLost); + on(_onBonusBallLost); on(_onScored); on(_onBonusLetterActivated); on(_onDashNestActivated); @@ -19,9 +20,11 @@ class GameBloc extends Bloc { static const bonusWordScore = 10000; void _onBallLost(BallLost event, Emitter emit) { - if (state.balls > 0) { - emit(state.copyWith(balls: state.balls - 1)); - } + emit(state.copyWith(balls: state.balls - 1)); + } + + void _onBonusBallLost(BonusBallLost event, Emitter emit) { + emit(state.copyWith(bonusBalls: state.bonusBalls - 1)); } void _onScored(Scored event, Emitter emit) { diff --git a/lib/game/components/wall.dart b/lib/game/components/wall.dart index 030edc50..ba8af5e7 100644 --- a/lib/game/components/wall.dart +++ b/lib/game/components/wall.dart @@ -71,12 +71,12 @@ class BottomWall extends Wall { } /// {@template bottom_wall_ball_contact_callback} -/// Listens when a [Ball] falls into a [BottomWall]. +/// Listens when a [ControlledBall] falls into a [BottomWall]. /// {@endtemplate} -class BottomWallBallContactCallback extends ContactCallback { +class BottomWallBallContactCallback + extends ContactCallback { @override - void begin(Ball ball, BottomWall wall, Contact contact) { - // TODO(alestiago): replace with .firstChild when available. - ball.children.whereType().first.lost(); + void begin(ControlledBall ball, BottomWall wall, Contact contact) { + ball.controller.lost(); } } diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index ff02c8b8..2f4401d9 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -30,21 +30,23 @@ class PinballGame extends Forge2DGame final PinballAudio audio; - @override - void onAttach() { - super.onAttach(); - controller.spawnBall(); - } - @override Future onLoad() async { - await super.onLoad(); _addContactCallbacks(); + // Fix camera on the center of the board. + camera + ..followVector2(Vector2(0, -7.8)) + ..zoom = size.y / 16; await _addGameBoundaries(); unawaited(addFromBlueprint(Boundaries())); unawaited(addFromBlueprint(LaunchRamp())); - unawaited(_addPlunger()); + + final plunger = Plunger(compressionDistance: 29) + ..initialPosition = + BoardDimensions.bounds.center.toVector2() + Vector2(41.5, -49); + await add(plunger); + unawaited(add(Board())); unawaited(addFromBlueprint(DinoWalls())); unawaited(_addBonusWord()); @@ -62,10 +64,8 @@ class PinballGame extends Forge2DGame ), ); - // Fix camera on the center of the board. - camera - ..followVector2(Vector2(0, -7.8)) - ..zoom = size.y / 16; + controller.attachTo(plunger); + await super.onLoad(); } void _addContactCallbacks() { @@ -79,13 +79,6 @@ class PinballGame extends Forge2DGame createBoundaries(this).forEach(add); } - Future _addPlunger() async { - final plunger = Plunger(compressionDistance: 29) - ..initialPosition = - BoardDimensions.bounds.center.toVector2() + Vector2(41.5, -49); - await add(plunger); - } - Future _addBonusWord() async { await add( BonusWord( @@ -102,9 +95,10 @@ class _GameBallsController extends ComponentController with BlocComponent, HasGameRef { _GameBallsController(PinballGame game) : super(game); + Plunger? _plunger; + @override bool listenWhen(GameState? previousState, GameState newState) { - // TODO(alestiago): Fix how the logic works. final previousBalls = (previousState?.balls ?? 0) + (previousState?.bonusBalls ?? 0); final currentBalls = newState.balls + newState.bonusBalls; @@ -119,20 +113,29 @@ class _GameBallsController extends ComponentController spawnBall(); } - Future spawnBall() async { - // TODO(alestiago): Remove once this logic is moved to controller. - var plunger = firstChild(); - if (plunger == null) { - await add(plunger = Plunger(compressionDistance: 1)); - } + @override + Future onLoad() async { + await super.onLoad(); + spawnBall(); + } + + void spawnBall() { + if (_plunger == null) return; final ball = ControlledBall.launch( theme: gameRef.theme, )..initialPosition = Vector2( - plunger.body.position.x, - plunger.body.position.y + Ball.size.y, + _plunger!.body.position.x, + _plunger!.body.position.y + Ball.size.y, ); - await add(ball); + component.add(ball); + } + + /// Attaches the controller to the plunger. + // TODO(alestiago): Remove this method and use onLoad instead. + // ignore: use_setters_to_change_properties + void attachTo(Plunger plunger) { + _plunger = plunger; } }