From 615361324e5d61aec2948d9d8496edce489e0c7f Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Sun, 8 May 2022 19:25:38 +0200 Subject: [PATCH] feat: reset and blinking on ramp --- lib/game/bloc/game_state.dart | 3 + .../android_acres/android_acres.dart | 48 +++++++----- .../android_acres/behaviors/behaviors.dart | 1 + .../behaviors/ramp_progress_behavior.dart | 77 +++++++------------ .../behaviors/ramp_reset_behavior.dart | 34 ++++++++ .../ramp_arrow_blinking_behavior.dart | 16 ++-- .../cubit/spaceship_ramp_cubit.dart | 7 +- .../cubit/spaceship_ramp_state.dart | 4 + .../spaceship_ramp/spaceship_ramp.dart | 37 +++------ 9 files changed, 121 insertions(+), 106 deletions(-) create mode 100644 lib/game/components/android_acres/behaviors/ramp_reset_behavior.dart diff --git a/lib/game/bloc/game_state.dart b/lib/game/bloc/game_state.dart index 8fcab789..1ba8457e 100644 --- a/lib/game/bloc/game_state.dart +++ b/lib/game/bloc/game_state.dart @@ -82,6 +82,9 @@ class GameState extends Equatable { /// The score displayed at the game. int get displayScore => roundScore + totalScore; + /// The max multiplier in game. + bool get isMaxMultiplier => multiplier == 6; + GameState copyWith({ int? totalScore, int? roundScore, diff --git a/lib/game/components/android_acres/android_acres.dart b/lib/game/components/android_acres/android_acres.dart index 1b43dc54..623a919f 100644 --- a/lib/game/components/android_acres/android_acres.dart +++ b/lib/game/components/android_acres/android_acres.dart @@ -16,8 +16,8 @@ class AndroidAcres extends Component { AndroidAcres() : super( children: [ - FlameBlocProvider( - create: AndroidSpaceshipCubit.new, + FlameBlocProvider( + create: SpaceshipRampCubit.new, children: [ SpaceshipRamp( children: [ @@ -25,33 +25,39 @@ class AndroidAcres extends Component { RampBonusBehavior(points: Points.oneMillion), RampProgressBehavior(), RampMultiplierBehavior(), + RampResetBehavior(), ], ), - SpaceshipRail(), + ], + ), + SpaceshipRail(), + AndroidBumper.a( + children: [ + ScoringContactBehavior(points: Points.twentyThousand), + BumperNoiseBehavior(), + ], + )..initialPosition = Vector2(-25.2, 1.5), + AndroidBumper.b( + children: [ + ScoringContactBehavior(points: Points.twentyThousand), + BumperNoiseBehavior(), + ], + )..initialPosition = Vector2(-32.9, -9.3), + AndroidBumper.cow( + children: [ + ScoringContactBehavior(points: Points.twentyThousand), + BumperNoiseBehavior(), + ], + )..initialPosition = Vector2(-20.7, -13), + FlameBlocProvider( + create: AndroidSpaceshipCubit.new, + children: [ AndroidSpaceship(position: Vector2(-26.5, -28.5)), AndroidAnimatronic( children: [ ScoringContactBehavior(points: Points.twoHundredThousand), ], )..initialPosition = Vector2(-26, -28.25), - AndroidBumper.a( - children: [ - ScoringContactBehavior(points: Points.twentyThousand), - BumperNoiseBehavior(), - ], - )..initialPosition = Vector2(-25.2, 1.5), - AndroidBumper.b( - children: [ - ScoringContactBehavior(points: Points.twentyThousand), - BumperNoiseBehavior(), - ], - )..initialPosition = Vector2(-32.9, -9.3), - AndroidBumper.cow( - children: [ - ScoringContactBehavior(points: Points.twentyThousand), - BumperNoiseBehavior(), - ], - )..initialPosition = Vector2(-20.7, -13), AndroidSpaceshipBonusBehavior(), ], ), diff --git a/lib/game/components/android_acres/behaviors/behaviors.dart b/lib/game/components/android_acres/behaviors/behaviors.dart index ddf7d766..c4e44a6e 100644 --- a/lib/game/components/android_acres/behaviors/behaviors.dart +++ b/lib/game/components/android_acres/behaviors/behaviors.dart @@ -2,4 +2,5 @@ export 'android_spaceship_bonus_behavior.dart'; export 'ramp_bonus_behavior.dart'; export 'ramp_multiplier_behavior.dart'; export 'ramp_progress_behavior.dart'; +export 'ramp_reset_behavior.dart'; export 'ramp_shot_behavior.dart'; diff --git a/lib/game/components/android_acres/behaviors/ramp_progress_behavior.dart b/lib/game/components/android_acres/behaviors/ramp_progress_behavior.dart index c74d472b..b8852b30 100644 --- a/lib/game/components/android_acres/behaviors/ramp_progress_behavior.dart +++ b/lib/game/components/android_acres/behaviors/ramp_progress_behavior.dart @@ -8,66 +8,43 @@ import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; /// {@template ramp_progress_behavior} -/// Increases the score when a [Ball] is shot into the [SpaceshipRamp]. +/// Changes arrow lit when a [Ball] is shot into the [SpaceshipRamp]. /// {@endtemplate} -class RampProgressBehavior extends Component - with ParentIsA, FlameBlocReader { - /// {@macro ramp_shot_behavior} +class RampProgressBehavior extends Component with ParentIsA { + /// {@macro ramp_progress_behavior} RampProgressBehavior() : super(); /// Creates a [RampProgressBehavior]. /// /// This can be used for testing [RampProgressBehavior] in isolation. @visibleForTesting - RampProgressBehavior.test({ - required this.subscription, - }) : super(); - - /// Subscription to [SpaceshipRampState] at [SpaceshipRamp]. - @visibleForTesting - StreamSubscription? subscription; + RampProgressBehavior.test() : super(); @override - void onMount() { - super.onMount(); - - var previousState = const SpaceshipRampState.initial(); - - subscription = subscription ?? - parent.bloc.stream.listen((state) { - print("STATE $state"); - final listenWhen = - previousState.hits != state.hits && state.hits != 0; - if (listenWhen) { - var fullArrowLit = parent.bloc.isFullyProgressed(); - var isMaxMultiplier = bloc.state.multiplier == 6; - final canProgress = - !isMaxMultiplier || (isMaxMultiplier && !fullArrowLit); - - print("fullArrowLit $fullArrowLit"); - print("isMaxMultiplier $isMaxMultiplier"); - print("canProgress $canProgress"); - if (canProgress) { - print("onProgressed"); - parent.bloc.onProgressed(); - } - - fullArrowLit = parent.bloc.isFullyProgressed(); - isMaxMultiplier = bloc.state.multiplier == 6; - - if (fullArrowLit && !isMaxMultiplier) { - print("onAnimate"); - parent.bloc.onAnimate(); - } - - previousState = state; + Future onLoad() async { + await super.onLoad(); + await add( + FlameBlocListener( + listenWhen: (previousState, newState) => + previousState.hits != newState.hits && newState.hits != 0, + onNewState: (state) { + final gameBloc = readBloc(); + final spaceshipCubit = + readBloc(); + + final canProgress = !gameBloc.state.isMaxMultiplier || + (gameBloc.state.isMaxMultiplier && !state.fullArrowLit); + + if (canProgress) { + spaceshipCubit.onProgressed(); } - }); - } - @override - void onRemove() { - subscription?.cancel(); - super.onRemove(); + if (spaceshipCubit.state.fullArrowLit && + !gameBloc.state.isMaxMultiplier) { + spaceshipCubit.onAnimate(); + } + }, + ), + ); } } diff --git a/lib/game/components/android_acres/behaviors/ramp_reset_behavior.dart b/lib/game/components/android_acres/behaviors/ramp_reset_behavior.dart new file mode 100644 index 00000000..317f2ce2 --- /dev/null +++ b/lib/game/components/android_acres/behaviors/ramp_reset_behavior.dart @@ -0,0 +1,34 @@ +import 'package:flame/components.dart'; +import 'package:flame_bloc/flame_bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +/// {@template ramp_reset_behavior} +/// Reset [SpaceshipRamp] state when GameState.rounds changes. +/// /// {@endtemplate} +class RampResetBehavior extends Component with ParentIsA { + /// {@macro ramp_reset_behavior} + RampResetBehavior() : super(); + + /// Creates a [RampResetBehavior]. + /// + /// This can be used for testing [RampResetBehavior] in isolation. + @visibleForTesting + RampResetBehavior.test() : super(); + + @override + Future onLoad() async { + await super.onLoad(); + await add( + FlameBlocListener( + listenWhen: (previousState, newState) => + previousState.rounds != newState.rounds, + onNewState: (state) { + readBloc().onReset(); + }, + ), + ); + } +} diff --git a/packages/pinball_components/lib/src/components/spaceship_ramp/behavior/ramp_arrow_blinking_behavior.dart b/packages/pinball_components/lib/src/components/spaceship_ramp/behavior/ramp_arrow_blinking_behavior.dart index dee9b436..35b3f81f 100644 --- a/packages/pinball_components/lib/src/components/spaceship_ramp/behavior/ramp_arrow_blinking_behavior.dart +++ b/packages/pinball_components/lib/src/components/spaceship_ramp/behavior/ramp_arrow_blinking_behavior.dart @@ -1,16 +1,18 @@ import 'package:flame/components.dart'; +import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; /// {@template ramp_arrow_blinking_behavior} -/// Makes a [SpaceshipRampArrowSpriteComponent] blink between [ArrowLightState.values]. +/// Makes a [SpaceshipRampArrowSpriteComponent] blink between +/// [ArrowLightState.values]. /// {@endtemplate} class RampArrowBlinkingBehavior extends TimerComponent with ParentIsA { /// {@macro ramp_arrow_blinking_behavior} RampArrowBlinkingBehavior() : super(period: 0.05); - final _maxBlinks = 15; + final _maxBlinks = 20; int _blinksCounter = 0; @@ -39,7 +41,7 @@ class RampArrowBlinkingBehavior extends TimerComponent } void _animate() { - parent.bloc.onBlink(); + readBloc().onBlink(); _blinksCounter++; } @@ -48,14 +50,18 @@ class RampArrowBlinkingBehavior extends TimerComponent _isAnimating = false; timer.stop(); _blinksCounter = 0; - parent.bloc.onStop(); + readBloc().onStop(); } } @override Future onLoad() async { await super.onLoad(); - parent.bloc.stream.listen(_onNewState); + await add( + FlameBlocListener( + onNewState: _onNewState, + ), + ); } @override diff --git a/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_cubit.dart b/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_cubit.dart index 484bea99..f6d230e4 100644 --- a/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_cubit.dart +++ b/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_cubit.dart @@ -24,13 +24,10 @@ class SpaceshipRampCubit extends Cubit { ); } - bool isFullyProgressed() => - state.lightState == ArrowLightState.active5 && - state.animationState == ArrowAnimationState.idle; - void onReset() { emit( - state.copyWith( + const SpaceshipRampState( + hits: 0, lightState: ArrowLightState.inactive, animationState: ArrowAnimationState.idle, ), diff --git a/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_state.dart b/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_state.dart index bc5a3a9c..2a8678f5 100644 --- a/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_state.dart +++ b/packages/pinball_components/lib/src/components/spaceship_ramp/cubit/spaceship_ramp_state.dart @@ -20,6 +20,10 @@ class SpaceshipRampState extends Equatable { final ArrowLightState lightState; final ArrowAnimationState animationState; + bool get fullArrowLit => + lightState == ArrowLightState.active5 && + animationState == ArrowAnimationState.idle; + SpaceshipRampState copyWith({ int? hits, ArrowLightState? lightState, diff --git a/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart b/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart index 92119cf3..1ce14ec1 100644 --- a/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart +++ b/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart @@ -1,6 +1,7 @@ import 'dart:math' as math; import 'package:flame/components.dart'; +import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/material.dart'; import 'package:pinball_components/gen/assets.gen.dart'; @@ -19,12 +20,10 @@ class SpaceshipRamp extends Component { Iterable? children, }) : this._( children: children, - bloc: SpaceshipRampCubit(), ); SpaceshipRamp._({ Iterable? children, - required this.bloc, }) : super( children: [ _SpaceshipRampOpening( @@ -39,9 +38,7 @@ class SpaceshipRamp extends Component { _SpaceshipRampForegroundRailing(), SpaceshipRampBase()..initialPosition = Vector2(3.4, -42.5), _SpaceshipRampBackgroundRailingSpriteComponent(), - SpaceshipRampArrowSpriteComponent( - current: bloc.state.lightState, - ), + SpaceshipRampArrowSpriteComponent(), RampArrowBlinkingBehavior(), ...?children, ], @@ -51,17 +48,7 @@ class SpaceshipRamp extends Component { /// /// This can be used for testing [SpaceshipRamp]'s behaviors in isolation. @visibleForTesting - SpaceshipRamp.test({ - required this.bloc, - }) : super(); - - final SpaceshipRampCubit bloc; - - @override - void onRemove() { - bloc.close(); - super.onRemove(); - } + SpaceshipRamp.test() : super(); } class _SpaceshipRampBackground extends BodyComponent @@ -172,12 +159,10 @@ class SpaceshipRampArrowSpriteComponent extends SpriteGroupComponent with HasGameRef, ParentIsA, ZIndex { /// {@macro spaceship_ramp_arrow_sprite_component} - SpaceshipRampArrowSpriteComponent({ - required ArrowLightState current, - }) : super( + SpaceshipRampArrowSpriteComponent() + : super( anchor: Anchor.center, position: Vector2(-3.9, -56.5), - current: current, ) { zIndex = ZIndexes.spaceshipRampArrow; } @@ -185,15 +170,17 @@ class SpaceshipRampArrowSpriteComponent @override Future onLoad() async { await super.onLoad(); - parent.bloc.stream.listen((state) { - print("STATE $state"); - current = state.lightState; - }); + await add( + FlameBlocListener( + listenWhen: (previousState, newState) => + previousState.lightState != newState.lightState, + onNewState: (state) => current = state.lightState, + ), + ); final sprites = {}; this.sprites = sprites; for (final spriteState in ArrowLightState.values) { - print("SPRITE $spriteState"); sprites[spriteState] = Sprite( gameRef.images.fromCache(spriteState.path), );