feat: implemented GameBallsController

pull/151/head
alestiago 4 years ago
parent ee86c83907
commit bd714ee269

@ -1,5 +1,4 @@
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/forge2d_game.dart'; import 'package:flame_forge2d/forge2d_game.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pinball/flame/flame.dart'; import 'package:pinball/flame/flame.dart';
@ -34,7 +33,7 @@ class ControlledBall extends Ball with Controls<BallController> {
/// [Ball] used in [DebugPinballGame]. /// [Ball] used in [DebugPinballGame].
ControlledBall.debug() : super(baseColor: const Color(0xFFFF0000)) { ControlledBall.debug() : super(baseColor: const Color(0xFFFF0000)) {
controller = BonusBallController(this); controller = _DebugBallController(this);
} }
} }
@ -51,7 +50,10 @@ abstract class BallController extends ComponentController<Ball> {
/// Triggered by [BottomWallBallContactCallback] when the [Ball] falls into /// Triggered by [BottomWallBallContactCallback] when the [Ball] falls into
/// a [BottomWall]. /// a [BottomWall].
/// {@endtemplate} /// {@endtemplate}
void lost(); @mustCallSuper
void lost() {
component.shouldRemove = true;
}
} }
/// {@template bonus_ball_controller} /// {@template bonus_ball_controller}
@ -59,24 +61,13 @@ abstract class BallController extends ComponentController<Ball> {
/// ///
/// A [BonusBallController] doesn't change the [GameState.balls] count. /// A [BonusBallController] doesn't change the [GameState.balls] count.
/// {@endtemplate} /// {@endtemplate}
class BonusBallController extends BallController class BonusBallController extends BallController with HasGameRef<PinballGame> {
with HasGameRef<PinballGame>, BlocComponent<GameBloc, GameState> {
/// {@macro bonus_ball_controller} /// {@macro bonus_ball_controller}
BonusBallController(Ball<Forge2DGame> component) : super(component); BonusBallController(Ball<Forge2DGame> component) : super(component);
@override
bool listenWhen(GameState? previousState, GameState newState) {
return (previousState?.balls ?? 0) > newState.balls;
}
@override
void onNewState(GameState state) {
super.onNewState(state);
component.shouldRemove = true;
}
@override @override
void lost() { void lost() {
super.lost();
gameRef.read<GameBloc>().add(const BonusBallLost()); gameRef.read<GameBloc>().add(const BonusBallLost());
} }
} }
@ -87,28 +78,21 @@ class BonusBallController extends BallController
/// A [LaunchedBallController] changes the [GameState.balls] count. /// A [LaunchedBallController] changes the [GameState.balls] count.
/// {@endtemplate} /// {@endtemplate}
class LaunchedBallController extends BallController class LaunchedBallController extends BallController
with HasGameRef<PinballGame>, BlocComponent<GameBloc, GameState> { with HasGameRef<PinballGame> {
/// {@macro launched_ball_controller} /// {@macro launched_ball_controller}
LaunchedBallController(Ball<Forge2DGame> ball) : super(ball); LaunchedBallController(Ball<Forge2DGame> ball) : super(ball);
@override
bool listenWhen(GameState? previousState, GameState newState) {
return (previousState?.balls ?? 0) > newState.balls;
}
@override
void onNewState(GameState state) {
super.onNewState(state);
component.shouldRemove = true;
if (state.balls > 0) gameRef.spawnBall();
}
/// Removes the [Ball] from a [PinballGame]; spawning a new [Ball] if /// Removes the [Ball] from a [PinballGame]; spawning a new [Ball] if
/// any are left. /// any are left.
/// ///
/// {@macro ball_controller_lost} /// {@macro ball_controller_lost}
@override @override
void lost() { void lost() {
super.lost();
gameRef.read<GameBloc>().add(const BallLost()); gameRef.read<GameBloc>().add(const BallLost());
} }
} }
class _DebugBallController extends BallController {
_DebugBallController(Ball<Forge2DGame> ball) : super(ball);
}

@ -6,6 +6,7 @@ import 'package:flame/extensions.dart';
import 'package:flame/input.dart'; import 'package:flame/input.dart';
import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/flame/flame.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/gen/assets.gen.dart'; import 'package:pinball/gen/assets.gen.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
@ -13,9 +14,16 @@ import 'package:pinball_components/pinball_components.dart' hide Assets;
import 'package:pinball_theme/pinball_theme.dart' hide Assets; import 'package:pinball_theme/pinball_theme.dart' hide Assets;
class PinballGame extends Forge2DGame class PinballGame extends Forge2DGame
with FlameBloc, HasKeyboardHandlerComponents { with
PinballGame({required this.theme, required this.audio}) { FlameBloc,
HasKeyboardHandlerComponents,
Controls<_GameBallsController> {
PinballGame({
required this.theme,
required this.audio,
}) {
images.prefix = ''; images.prefix = '';
controller = _GameBallsController(this);
} }
final PinballTheme theme; final PinballTheme theme;
@ -25,11 +33,12 @@ class PinballGame extends Forge2DGame
@override @override
void onAttach() { void onAttach() {
super.onAttach(); super.onAttach();
spawnBall(); controller.spawnBall();
} }
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad();
_addContactCallbacks(); _addContactCallbacks();
await _addGameBoundaries(); await _addGameBoundaries();
@ -87,6 +96,28 @@ class PinballGame extends Forge2DGame
), ),
); );
} }
}
class _GameBallsController extends ComponentController<PinballGame>
with BlocComponent<GameBloc, GameState>, HasGameRef<PinballGame> {
_GameBallsController(PinballGame game) : super(game);
@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;
final canBallRespawn = newState.balls > 0 && newState.bonusBalls == 0;
return previousBalls != currentBalls && canBallRespawn;
}
@override
void onNewState(GameState state) {
super.onNewState(state);
spawnBall();
}
Future<void> spawnBall() async { Future<void> spawnBall() async {
// TODO(alestiago): Remove once this logic is moved to controller. // TODO(alestiago): Remove once this logic is moved to controller.
@ -96,7 +127,7 @@ class PinballGame extends Forge2DGame
} }
final ball = ControlledBall.launch( final ball = ControlledBall.launch(
theme: theme, theme: gameRef.theme,
)..initialPosition = Vector2( )..initialPosition = Vector2(
plunger.body.position.x, plunger.body.position.x,
plunger.body.position.y + Ball.size.y, plunger.body.position.y + Ball.size.y,

Loading…
Cancel
Save