refactor: multipliers cubit

pull/231/head
RuiAlonso 3 years ago
parent 8afd39c5f9
commit 05e3049205

@ -0,0 +1 @@
export 'multipliers_behavior.dart';

@ -0,0 +1,26 @@
import 'package:flame/components.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
/// Toggle each [Multiplier] when GameState.multiplier changes.
class MultipliersBehavior extends Component
with HasGameRef<PinballGame>, ParentIsA<Multipliers> {
@override
void onMount() {
super.onMount();
// TODO(ruimiguel): filter only when multiplier has change, not every other
// state.
gameRef.read<GameBloc>().stream.listen((state) {
final multipliers = parent.children.whereType<Multiplier>();
for (final multiplier in multipliers) {
// TODO(ruimiguel): use here GameState.multiplier when merged
// https://github.com/VGVentures/pinball/pull/213.
final currentMultiplier = state.score.bitLength % 6 + 1;
multiplier.bloc.toggle(currentMultiplier);
}
});
}
}

@ -0,0 +1,43 @@
// ignore_for_file: public_member_api_docs
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:pinball/game/components/multipliers/behaviors/behaviors.dart';
import 'package:pinball_components/pinball_components.dart';
/// {@template multipliers_component}
/// A group for the multipliers over the board.
/// {@endtemplate}
class Multipliers extends Component {
/// {@macro multipliers_component}
Multipliers()
: super(
children: [
Multiplier(
value: MultiplierValue.x2,
position: Vector2(-19.5, -2),
rotation: -15 * math.pi / 180,
),
Multiplier(
value: MultiplierValue.x3,
position: Vector2(13, -9.4),
rotation: 15 * math.pi / 180,
),
Multiplier(
value: MultiplierValue.x4,
position: Vector2(0, -21.2),
),
Multiplier(
value: MultiplierValue.x5,
position: Vector2(-8.5, -28),
rotation: -3 * math.pi / 180,
),
Multiplier(
value: MultiplierValue.x6,
position: Vector2(10, -30.7),
rotation: 8 * math.pi / 180,
),
MultipliersBehavior(),
],
);
}

@ -19,7 +19,7 @@ export 'kicker.dart';
export 'launch_ramp.dart'; export 'launch_ramp.dart';
export 'layer.dart'; export 'layer.dart';
export 'layer_sensor.dart'; export 'layer_sensor.dart';
export 'multiplier.dart'; export 'multiplier/multiplier.dart';
export 'plunger.dart'; export 'plunger.dart';
export 'render_priority.dart'; export 'render_priority.dart';
export 'rocket.dart'; export 'rocket.dart';

@ -0,0 +1,47 @@
// ignore_for_file: public_member_api_docs
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:pinball_components/pinball_components.dart';
part 'multiplier_state.dart';
class MultiplierCubit extends Cubit<MultiplierState> {
MultiplierCubit(MultiplierValue multiplierValue)
: super(
MultiplierState(
value: multiplierValue,
spriteState: MultiplierSpriteState.dimmed,
),
);
/// Event added when the game current multiplier changes.
void toggle(int multiplier) {
if (state.equalsTo(multiplier)) {
if (state.spriteState == MultiplierSpriteState.dimmed) {
emit(state.copyWith(spriteState: MultiplierSpriteState.lit));
}
} else {
if (state.spriteState == MultiplierSpriteState.lit) {
emit(state.copyWith(spriteState: MultiplierSpriteState.dimmed));
}
}
}
}
extension on MultiplierState {
bool equalsTo(int value) {
switch (this.value) {
case MultiplierValue.x2:
return value == 2;
case MultiplierValue.x3:
return value == 3;
case MultiplierValue.x4:
return value == 4;
case MultiplierValue.x5:
return value == 5;
case MultiplierValue.x6:
return value == 6;
}
}
}

@ -0,0 +1,35 @@
// ignore_for_file: public_member_api_docs
part of 'multiplier_cubit.dart';
/// Indicates the different sprite states for [MultiplierSpriteGroupComponent].
enum MultiplierSpriteState {
lit,
dimmed,
}
/// Indicates the [MultiplierCubit]'s current state.
class MultiplierState extends Equatable {
const MultiplierState({
required this.value,
required this.spriteState,
});
/// Current value for the [Multiplier]
final MultiplierValue value;
/// The [MultiplierSpriteGroupComponent] current sprite state
final MultiplierSpriteState spriteState;
MultiplierState copyWith({
MultiplierSpriteState? spriteState,
}) {
return MultiplierState(
value: value,
spriteState: spriteState ?? this.spriteState,
);
}
@override
List<Object> get props => [value, spriteState];
}

@ -3,6 +3,10 @@
import 'package:flame/components.dart'; import 'package:flame/components.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';
import 'package:pinball_components/src/components/multiplier/cubit/multiplier_cubit.dart';
import 'package:pinball_flame/pinball_flame.dart';
export 'cubit/multiplier_cubit.dart';
/// {@template multiplier} /// {@template multiplier}
/// A [Component] for the multiplier over the board. /// A [Component] for the multiplier over the board.
@ -14,29 +18,50 @@ class Multiplier extends Component {
required Vector2 position, required Vector2 position,
double rotation = 0, double rotation = 0,
}) : _value = value, }) : _value = value,
_sprite = MultiplierSpriteGroupComponent( _position = position,
position: position, _rotation = rotation,
litAssetPath: value.litAssetPath, bloc = MultiplierCubit(value),
dimmedAssetPath: value.dimmedAssetPath, super();
rotation: rotation,
);
final MultiplierValue _value; final MultiplierValue _value;
final MultiplierSpriteGroupComponent _sprite; final Vector2 _position;
final double _rotation;
late final MultiplierSpriteGroupComponent _sprite;
/// Creates a [Multiplier] without any children.
///
/// This can be used for testing [Multiplier]'s behaviors in isolation.
// TODO(alestiago): Refactor injecting bloc once the following is merged:
// https://github.com/flame-engine/flame/pull/1538
@visibleForTesting
Multiplier.test({
required MultiplierValue value,
required this.bloc,
}) : _value = value,
_position = Vector2.zero(),
_rotation = 0;
/// Change current [Sprite] to active or inactive depending on applied // TODO(ruimiguel): Consider refactoring once the following is merged:
/// multiplier. // https://github.com/flame-engine/flame/pull/1538
void toggle(int multiplier) { // ignore: public_member_api_docs
if (_value.equalsTo(multiplier)) { final MultiplierCubit bloc;
_sprite.current = MultiplierSpriteState.lit;
} else { @override
_sprite.current = MultiplierSpriteState.dimmed; void onRemove() {
} bloc.close();
super.onRemove();
} }
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
_sprite = MultiplierSpriteGroupComponent(
position: _position,
litAssetPath: _value.litAssetPath,
dimmedAssetPath: _value.dimmedAssetPath,
rotation: _rotation,
current: bloc.state,
);
await add(_sprite); await add(_sprite);
} }
} }
@ -50,15 +75,6 @@ enum MultiplierValue {
x6, x6,
} }
/// Indicates the current sprite state of the multiplier.
enum MultiplierSpriteState {
/// A lit up bumper.
lit,
/// A dimmed bumper.
dimmed,
}
extension on MultiplierValue { extension on MultiplierValue {
String get litAssetPath { String get litAssetPath {
switch (this) { switch (this) {
@ -89,21 +105,6 @@ extension on MultiplierValue {
return Assets.images.multiplier.x6.dimmed.keyName; return Assets.images.multiplier.x6.dimmed.keyName;
} }
} }
bool equalsTo(int value) {
switch (this) {
case MultiplierValue.x2:
return value == 2;
case MultiplierValue.x3:
return value == 3;
case MultiplierValue.x4:
return value == 4;
case MultiplierValue.x5:
return value == 5;
case MultiplierValue.x6:
return value == 6;
}
}
} }
/// {@template multiplier_sprite_group_component} /// {@template multiplier_sprite_group_component}
@ -111,19 +112,22 @@ extension on MultiplierValue {
/// {@endtemplate} /// {@endtemplate}
@visibleForTesting @visibleForTesting
class MultiplierSpriteGroupComponent class MultiplierSpriteGroupComponent
extends SpriteGroupComponent<MultiplierSpriteState> with HasGameRef { extends SpriteGroupComponent<MultiplierSpriteState>
with HasGameRef, ParentIsA<Multiplier> {
/// {@macro multiplier_sprite_group_component} /// {@macro multiplier_sprite_group_component}
MultiplierSpriteGroupComponent({ MultiplierSpriteGroupComponent({
required Vector2 position, required Vector2 position,
required String litAssetPath, required String litAssetPath,
required String dimmedAssetPath, required String dimmedAssetPath,
required double rotation, required double rotation,
required MultiplierState current,
}) : _litAssetPath = litAssetPath, }) : _litAssetPath = litAssetPath,
_dimmedAssetPath = dimmedAssetPath, _dimmedAssetPath = dimmedAssetPath,
super( super(
anchor: Anchor.center, anchor: Anchor.center,
position: position, position: position,
angle: rotation, angle: rotation,
current: current.spriteState,
); );
final String _litAssetPath; final String _litAssetPath;
@ -132,6 +136,7 @@ class MultiplierSpriteGroupComponent
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
parent.bloc.stream.listen((state) => current = state.spriteState);
final sprites = { final sprites = {
MultiplierSpriteState.lit: MultiplierSpriteState.lit:
@ -140,8 +145,6 @@ class MultiplierSpriteGroupComponent
Sprite(gameRef.images.fromCache(_dimmedAssetPath)), Sprite(gameRef.images.fromCache(_dimmedAssetPath)),
}; };
this.sprites = sprites; this.sprites = sprites;
current = MultiplierSpriteState.dimmed;
size = sprites[current]!.originalSize / 10; size = sprites[current]!.originalSize / 10;
} }
} }
Loading…
Cancel
Save