feat: reset and blinking on ramp

pull/416/head
RuiAlonso 3 years ago
parent 2edba8c7d9
commit 615361324e

@ -82,6 +82,9 @@ class GameState extends Equatable {
/// The score displayed at the game. /// The score displayed at the game.
int get displayScore => roundScore + totalScore; int get displayScore => roundScore + totalScore;
/// The max multiplier in game.
bool get isMaxMultiplier => multiplier == 6;
GameState copyWith({ GameState copyWith({
int? totalScore, int? totalScore,
int? roundScore, int? roundScore,

@ -16,8 +16,8 @@ class AndroidAcres extends Component {
AndroidAcres() AndroidAcres()
: super( : super(
children: [ children: [
FlameBlocProvider<AndroidSpaceshipCubit, AndroidSpaceshipState>( FlameBlocProvider<SpaceshipRampCubit, SpaceshipRampState>(
create: AndroidSpaceshipCubit.new, create: SpaceshipRampCubit.new,
children: [ children: [
SpaceshipRamp( SpaceshipRamp(
children: [ children: [
@ -25,33 +25,39 @@ class AndroidAcres extends Component {
RampBonusBehavior(points: Points.oneMillion), RampBonusBehavior(points: Points.oneMillion),
RampProgressBehavior(), RampProgressBehavior(),
RampMultiplierBehavior(), 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<AndroidSpaceshipCubit, AndroidSpaceshipState>(
create: AndroidSpaceshipCubit.new,
children: [
AndroidSpaceship(position: Vector2(-26.5, -28.5)), AndroidSpaceship(position: Vector2(-26.5, -28.5)),
AndroidAnimatronic( AndroidAnimatronic(
children: [ children: [
ScoringContactBehavior(points: Points.twoHundredThousand), ScoringContactBehavior(points: Points.twoHundredThousand),
], ],
)..initialPosition = Vector2(-26, -28.25), )..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(), AndroidSpaceshipBonusBehavior(),
], ],
), ),

@ -2,4 +2,5 @@ export 'android_spaceship_bonus_behavior.dart';
export 'ramp_bonus_behavior.dart'; export 'ramp_bonus_behavior.dart';
export 'ramp_multiplier_behavior.dart'; export 'ramp_multiplier_behavior.dart';
export 'ramp_progress_behavior.dart'; export 'ramp_progress_behavior.dart';
export 'ramp_reset_behavior.dart';
export 'ramp_shot_behavior.dart'; export 'ramp_shot_behavior.dart';

@ -8,66 +8,43 @@ import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_flame/pinball_flame.dart';
/// {@template ramp_progress_behavior} /// {@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} /// {@endtemplate}
class RampProgressBehavior extends Component class RampProgressBehavior extends Component with ParentIsA<SpaceshipRamp> {
with ParentIsA<SpaceshipRamp>, FlameBlocReader<GameBloc, GameState> { /// {@macro ramp_progress_behavior}
/// {@macro ramp_shot_behavior}
RampProgressBehavior() : super(); RampProgressBehavior() : super();
/// Creates a [RampProgressBehavior]. /// Creates a [RampProgressBehavior].
/// ///
/// This can be used for testing [RampProgressBehavior] in isolation. /// This can be used for testing [RampProgressBehavior] in isolation.
@visibleForTesting @visibleForTesting
RampProgressBehavior.test({ RampProgressBehavior.test() : super();
required this.subscription,
}) : super();
/// Subscription to [SpaceshipRampState] at [SpaceshipRamp].
@visibleForTesting
StreamSubscription? subscription;
@override @override
void onMount() { Future<void> onLoad() async {
super.onMount(); await super.onLoad();
await add(
var previousState = const SpaceshipRampState.initial(); FlameBlocListener<SpaceshipRampCubit, SpaceshipRampState>(
listenWhen: (previousState, newState) =>
subscription = subscription ?? previousState.hits != newState.hits && newState.hits != 0,
parent.bloc.stream.listen((state) { onNewState: (state) {
print("STATE $state"); final gameBloc = readBloc<GameBloc, GameState>();
final listenWhen = final spaceshipCubit =
previousState.hits != state.hits && state.hits != 0; readBloc<SpaceshipRampCubit, SpaceshipRampState>();
if (listenWhen) {
var fullArrowLit = parent.bloc.isFullyProgressed(); final canProgress = !gameBloc.state.isMaxMultiplier ||
var isMaxMultiplier = bloc.state.multiplier == 6; (gameBloc.state.isMaxMultiplier && !state.fullArrowLit);
final canProgress =
!isMaxMultiplier || (isMaxMultiplier && !fullArrowLit); if (canProgress) {
spaceshipCubit.onProgressed();
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;
} }
});
}
@override if (spaceshipCubit.state.fullArrowLit &&
void onRemove() { !gameBloc.state.isMaxMultiplier) {
subscription?.cancel(); spaceshipCubit.onAnimate();
super.onRemove(); }
},
),
);
} }
} }

@ -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<SpaceshipRamp> {
/// {@macro ramp_reset_behavior}
RampResetBehavior() : super();
/// Creates a [RampResetBehavior].
///
/// This can be used for testing [RampResetBehavior] in isolation.
@visibleForTesting
RampResetBehavior.test() : super();
@override
Future<void> onLoad() async {
await super.onLoad();
await add(
FlameBlocListener<GameBloc, GameState>(
listenWhen: (previousState, newState) =>
previousState.rounds != newState.rounds,
onNewState: (state) {
readBloc<SpaceshipRampCubit, SpaceshipRampState>().onReset();
},
),
);
}
}

@ -1,16 +1,18 @@
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_flame/pinball_flame.dart';
/// {@template ramp_arrow_blinking_behavior} /// {@template ramp_arrow_blinking_behavior}
/// Makes a [SpaceshipRampArrowSpriteComponent] blink between [ArrowLightState.values]. /// Makes a [SpaceshipRampArrowSpriteComponent] blink between
/// [ArrowLightState.values].
/// {@endtemplate} /// {@endtemplate}
class RampArrowBlinkingBehavior extends TimerComponent class RampArrowBlinkingBehavior extends TimerComponent
with ParentIsA<SpaceshipRamp> { with ParentIsA<SpaceshipRamp> {
/// {@macro ramp_arrow_blinking_behavior} /// {@macro ramp_arrow_blinking_behavior}
RampArrowBlinkingBehavior() : super(period: 0.05); RampArrowBlinkingBehavior() : super(period: 0.05);
final _maxBlinks = 15; final _maxBlinks = 20;
int _blinksCounter = 0; int _blinksCounter = 0;
@ -39,7 +41,7 @@ class RampArrowBlinkingBehavior extends TimerComponent
} }
void _animate() { void _animate() {
parent.bloc.onBlink(); readBloc<SpaceshipRampCubit, SpaceshipRampState>().onBlink();
_blinksCounter++; _blinksCounter++;
} }
@ -48,14 +50,18 @@ class RampArrowBlinkingBehavior extends TimerComponent
_isAnimating = false; _isAnimating = false;
timer.stop(); timer.stop();
_blinksCounter = 0; _blinksCounter = 0;
parent.bloc.onStop(); readBloc<SpaceshipRampCubit, SpaceshipRampState>().onStop();
} }
} }
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
parent.bloc.stream.listen(_onNewState); await add(
FlameBlocListener<SpaceshipRampCubit, SpaceshipRampState>(
onNewState: _onNewState,
),
);
} }
@override @override

@ -24,13 +24,10 @@ class SpaceshipRampCubit extends Cubit<SpaceshipRampState> {
); );
} }
bool isFullyProgressed() =>
state.lightState == ArrowLightState.active5 &&
state.animationState == ArrowAnimationState.idle;
void onReset() { void onReset() {
emit( emit(
state.copyWith( const SpaceshipRampState(
hits: 0,
lightState: ArrowLightState.inactive, lightState: ArrowLightState.inactive,
animationState: ArrowAnimationState.idle, animationState: ArrowAnimationState.idle,
), ),

@ -20,6 +20,10 @@ class SpaceshipRampState extends Equatable {
final ArrowLightState lightState; final ArrowLightState lightState;
final ArrowAnimationState animationState; final ArrowAnimationState animationState;
bool get fullArrowLit =>
lightState == ArrowLightState.active5 &&
animationState == ArrowAnimationState.idle;
SpaceshipRampState copyWith({ SpaceshipRampState copyWith({
int? hits, int? hits,
ArrowLightState? lightState, ArrowLightState? lightState,

@ -1,6 +1,7 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pinball_components/gen/assets.gen.dart'; import 'package:pinball_components/gen/assets.gen.dart';
@ -19,12 +20,10 @@ class SpaceshipRamp extends Component {
Iterable<Component>? children, Iterable<Component>? children,
}) : this._( }) : this._(
children: children, children: children,
bloc: SpaceshipRampCubit(),
); );
SpaceshipRamp._({ SpaceshipRamp._({
Iterable<Component>? children, Iterable<Component>? children,
required this.bloc,
}) : super( }) : super(
children: [ children: [
_SpaceshipRampOpening( _SpaceshipRampOpening(
@ -39,9 +38,7 @@ class SpaceshipRamp extends Component {
_SpaceshipRampForegroundRailing(), _SpaceshipRampForegroundRailing(),
SpaceshipRampBase()..initialPosition = Vector2(3.4, -42.5), SpaceshipRampBase()..initialPosition = Vector2(3.4, -42.5),
_SpaceshipRampBackgroundRailingSpriteComponent(), _SpaceshipRampBackgroundRailingSpriteComponent(),
SpaceshipRampArrowSpriteComponent( SpaceshipRampArrowSpriteComponent(),
current: bloc.state.lightState,
),
RampArrowBlinkingBehavior(), RampArrowBlinkingBehavior(),
...?children, ...?children,
], ],
@ -51,17 +48,7 @@ class SpaceshipRamp extends Component {
/// ///
/// This can be used for testing [SpaceshipRamp]'s behaviors in isolation. /// This can be used for testing [SpaceshipRamp]'s behaviors in isolation.
@visibleForTesting @visibleForTesting
SpaceshipRamp.test({ SpaceshipRamp.test() : super();
required this.bloc,
}) : super();
final SpaceshipRampCubit bloc;
@override
void onRemove() {
bloc.close();
super.onRemove();
}
} }
class _SpaceshipRampBackground extends BodyComponent class _SpaceshipRampBackground extends BodyComponent
@ -172,12 +159,10 @@ class SpaceshipRampArrowSpriteComponent
extends SpriteGroupComponent<ArrowLightState> extends SpriteGroupComponent<ArrowLightState>
with HasGameRef, ParentIsA<SpaceshipRamp>, ZIndex { with HasGameRef, ParentIsA<SpaceshipRamp>, ZIndex {
/// {@macro spaceship_ramp_arrow_sprite_component} /// {@macro spaceship_ramp_arrow_sprite_component}
SpaceshipRampArrowSpriteComponent({ SpaceshipRampArrowSpriteComponent()
required ArrowLightState current, : super(
}) : super(
anchor: Anchor.center, anchor: Anchor.center,
position: Vector2(-3.9, -56.5), position: Vector2(-3.9, -56.5),
current: current,
) { ) {
zIndex = ZIndexes.spaceshipRampArrow; zIndex = ZIndexes.spaceshipRampArrow;
} }
@ -185,15 +170,17 @@ class SpaceshipRampArrowSpriteComponent
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
parent.bloc.stream.listen((state) { await add(
print("STATE $state"); FlameBlocListener<SpaceshipRampCubit, SpaceshipRampState>(
current = state.lightState; listenWhen: (previousState, newState) =>
}); previousState.lightState != newState.lightState,
onNewState: (state) => current = state.lightState,
),
);
final sprites = <ArrowLightState, Sprite>{}; final sprites = <ArrowLightState, Sprite>{};
this.sprites = sprites; this.sprites = sprites;
for (final spriteState in ArrowLightState.values) { for (final spriteState in ArrowLightState.values) {
print("SPRITE $spriteState");
sprites[spriteState] = Sprite( sprites[spriteState] = Sprite(
gameRef.images.fromCache(spriteState.path), gameRef.images.fromCache(spriteState.path),
); );

Loading…
Cancel
Save