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.
int get displayScore => roundScore + totalScore;
/// The max multiplier in game.
bool get isMaxMultiplier => multiplier == 6;
GameState copyWith({
int? totalScore,
int? roundScore,

@ -16,8 +16,8 @@ class AndroidAcres extends Component {
AndroidAcres()
: super(
children: [
FlameBlocProvider<AndroidSpaceshipCubit, AndroidSpaceshipState>(
create: AndroidSpaceshipCubit.new,
FlameBlocProvider<SpaceshipRampCubit, SpaceshipRampState>(
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<AndroidSpaceshipCubit, AndroidSpaceshipState>(
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(),
],
),

@ -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';

@ -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<SpaceshipRamp>, FlameBlocReader<GameBloc, GameState> {
/// {@macro ramp_shot_behavior}
class RampProgressBehavior extends Component with ParentIsA<SpaceshipRamp> {
/// {@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<void> onLoad() async {
await super.onLoad();
await add(
FlameBlocListener<SpaceshipRampCubit, SpaceshipRampState>(
listenWhen: (previousState, newState) =>
previousState.hits != newState.hits && newState.hits != 0,
onNewState: (state) {
final gameBloc = readBloc<GameBloc, GameState>();
final spaceshipCubit =
readBloc<SpaceshipRampCubit, SpaceshipRampState>();
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();
}
},
),
);
}
}

@ -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_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<SpaceshipRamp> {
/// {@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<SpaceshipRampCubit, SpaceshipRampState>().onBlink();
_blinksCounter++;
}
@ -48,14 +50,18 @@ class RampArrowBlinkingBehavior extends TimerComponent
_isAnimating = false;
timer.stop();
_blinksCounter = 0;
parent.bloc.onStop();
readBloc<SpaceshipRampCubit, SpaceshipRampState>().onStop();
}
}
@override
Future<void> onLoad() async {
await super.onLoad();
parent.bloc.stream.listen(_onNewState);
await add(
FlameBlocListener<SpaceshipRampCubit, SpaceshipRampState>(
onNewState: _onNewState,
),
);
}
@override

@ -24,13 +24,10 @@ class SpaceshipRampCubit extends Cubit<SpaceshipRampState> {
);
}
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,
),

@ -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,

@ -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<Component>? children,
}) : this._(
children: children,
bloc: SpaceshipRampCubit(),
);
SpaceshipRamp._({
Iterable<Component>? 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<ArrowLightState>
with HasGameRef, ParentIsA<SpaceshipRamp>, 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<void> onLoad() async {
await super.onLoad();
parent.bloc.stream.listen((state) {
print("STATE $state");
current = state.lightState;
});
await add(
FlameBlocListener<SpaceshipRampCubit, SpaceshipRampState>(
listenWhen: (previousState, newState) =>
previousState.lightState != newState.lightState,
onNewState: (state) => current = state.lightState,
),
);
final sprites = <ArrowLightState, Sprite>{};
this.sprites = sprites;
for (final spriteState in ArrowLightState.values) {
print("SPRITE $spriteState");
sprites[spriteState] = Sprite(
gameRef.images.fromCache(spriteState.path),
);

Loading…
Cancel
Save