refactor: changed bloc events names for multiplier

pull/213/head
RuiAlonso 3 years ago
commit d0590e8f56

@ -11,9 +11,9 @@ class GameBloc extends Bloc<GameEvent, GameState> {
GameBloc() : super(const GameState.initial()) {
on<BallLost>(_onBallLost);
on<Scored>(_onScored);
on<IncreasedMultiplier>(_onIncreasedMultiplier);
on<AppliedMultiplier>(_onAppliedMultiplier);
on<ResetMultiplier>(_onResetMultiplier);
on<MultiplierIncreased>(_onIncreasedMultiplier);
on<MultiplierApplied>(_onAppliedMultiplier);
on<MultiplierReset>(_onResetMultiplier);
on<BonusActivated>(_onBonusActivated);
on<SparkyTurboChargeActivated>(_onSparkyTurboChargeActivated);
}
@ -30,19 +30,19 @@ class GameBloc extends Bloc<GameEvent, GameState> {
}
}
void _onIncreasedMultiplier(IncreasedMultiplier event, Emitter emit) {
void _onIncreasedMultiplier(MultiplierIncreased event, Emitter emit) {
if (!state.isGameOver) {
emit(state.copyWith(multiplier: state.multiplier + event.increase));
}
}
void _onAppliedMultiplier(AppliedMultiplier event, Emitter emit) {
void _onAppliedMultiplier(MultiplierApplied event, Emitter emit) {
if (!state.isGameOver) {
emit(state.copyWith(score: state.score * state.multiplier));
}
}
void _onResetMultiplier(ResetMultiplier event, Emitter emit) {
void _onResetMultiplier(MultiplierReset event, Emitter emit) {
if (!state.isGameOver) {
emit(state.copyWith(multiplier: 1));
}

@ -49,12 +49,12 @@ class SparkyTurboChargeActivated extends GameEvent {
List<Object?> get props => [];
}
/// {@template increased_multiplier_game_event}
/// {@template multiplier_increased_game_event}
/// Event added when multiplier is being increased.
/// {@endtemplate}
class IncreasedMultiplier extends GameEvent {
/// {@macro increased_multiplier_game_event}
const IncreasedMultiplier({
class MultiplierIncreased extends GameEvent {
/// {@macro multiplier_increased_game_event}
const MultiplierIncreased({
required this.increase,
}) : assert(increase > 0, 'Increase must be greater than 0');
@ -64,23 +64,23 @@ class IncreasedMultiplier extends GameEvent {
List<Object?> get props => [increase];
}
/// {@template applied_multiplier_game_event}
/// {@template multiplier_applied_game_event}
/// Event added when multiplier is applied to score.
/// {@endtemplate}
class AppliedMultiplier extends GameEvent {
/// {@macro applied_multiplier_game_event}
const AppliedMultiplier();
class MultiplierApplied extends GameEvent {
/// {@macro multiplier_applied_game_event}
const MultiplierApplied();
@override
List<Object?> get props => [];
}
/// {@template reset_multiplier_game_event}
/// {@template multiplier_reset_game_event}
/// Event added when multiplier is reset.
/// {@endtemplate}
class ResetMultiplier extends GameEvent {
/// {@macro reset_multiplier_game_event}
const ResetMultiplier();
class MultiplierReset extends GameEvent {
/// {@macro multiplier_reset_game_event}
const MultiplierReset();
@override
List<Object?> get props => [];

@ -9,7 +9,6 @@ export 'flutter_forest.dart';
export 'game_flow_controller.dart';
export 'google_word.dart';
export 'launcher.dart';
export 'score_effect_controller.dart';
export 'score_points.dart';
export 'sparky_fire_zone.dart';
export 'wall.dart';

@ -1,45 +0,0 @@
import 'dart:math';
import 'package:flame/components.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
/// {@template score_effect_controller}
/// A [ComponentController] responsible for adding [ScoreText]s
/// on the game screen when the user earns points.
/// {@endtemplate}
class ScoreEffectController extends ComponentController<PinballGame>
with BlocComponent<GameBloc, GameState> {
/// {@macro score_effect_controller}
ScoreEffectController(PinballGame component) : super(component);
int _lastScore = 0;
final _random = Random();
double _noise() {
return _random.nextDouble() * 5 * (_random.nextBool() ? -1 : 1);
}
@override
bool listenWhen(GameState? previousState, GameState newState) {
return previousState?.score != newState.score;
}
@override
void onNewState(GameState state) {
final newScore = state.score - _lastScore;
_lastScore = state.score;
component.add(
ScoreText(
text: newScore.toString(),
position: Vector2(
_noise(),
_noise() + (BoardDimensions.bounds.topCenter.dy + 10),
),
),
);
}
}

@ -30,11 +30,18 @@ class BallScorePointsCallback extends ContactCallback<Ball, ScorePoints> {
@override
void begin(
Ball _,
Ball ball,
ScorePoints scorePoints,
Contact __,
Contact _,
) {
_gameRef.read<GameBloc>().add(Scored(points: scorePoints.points));
_gameRef.audio.score();
_gameRef.add(
ScoreText(
text: scorePoints.points.toString(),
position: ball.body.position,
),
);
}
}

@ -41,13 +41,30 @@ extension PinballGameAssetsX on PinballGame {
images.load(components.Assets.images.boundary.outer.keyName),
images.load(components.Assets.images.spaceship.saucer.keyName),
images.load(components.Assets.images.spaceship.bridge.keyName),
images.load(components.Assets.images.spaceship.ramp.main.keyName),
images.load(components.Assets.images.spaceship.ramp.boardOpening.keyName),
images.load(
components.Assets.images.spaceship.ramp.railingForeground.keyName,
),
images.load(
components.Assets.images.spaceship.ramp.railingBackground.keyName,
),
images.load(components.Assets.images.spaceship.ramp.main.keyName),
images
.load(components.Assets.images.spaceship.ramp.arrow.inactive.keyName),
images.load(
components.Assets.images.spaceship.ramp.railingForeground.keyName,
components.Assets.images.spaceship.ramp.arrow.active1.keyName,
),
images.load(
components.Assets.images.spaceship.ramp.arrow.active2.keyName,
),
images.load(
components.Assets.images.spaceship.ramp.arrow.active3.keyName,
),
images.load(
components.Assets.images.spaceship.ramp.arrow.active4.keyName,
),
images.load(
components.Assets.images.spaceship.ramp.arrow.active5.keyName,
),
images.load(components.Assets.images.spaceship.rail.main.keyName),
images.load(components.Assets.images.spaceship.rail.foreground.keyName),

@ -42,7 +42,6 @@ class PinballGame extends Forge2DGame
Future<void> onLoad() async {
_addContactCallbacks();
unawaited(add(ScoreEffectController(this)));
unawaited(add(gameFlowController = GameFlowController(this)));
unawaited(add(CameraController(this)));
unawaited(add(Backboard.waiting(position: Vector2(0, -88))));

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 19 KiB

@ -311,6 +311,9 @@ class $AssetsImagesSpaceshipRailGen {
class $AssetsImagesSpaceshipRampGen {
const $AssetsImagesSpaceshipRampGen();
$AssetsImagesSpaceshipRampArrowGen get arrow =>
const $AssetsImagesSpaceshipRampArrowGen();
/// File path: assets/images/spaceship/ramp/board-opening.png
AssetGenImage get boardOpening =>
const AssetGenImage('assets/images/spaceship/ramp/board-opening.png');
@ -384,6 +387,34 @@ class $AssetsImagesDashBumperMainGen {
const AssetGenImage('assets/images/dash/bumper/main/inactive.png');
}
class $AssetsImagesSpaceshipRampArrowGen {
const $AssetsImagesSpaceshipRampArrowGen();
/// File path: assets/images/spaceship/ramp/arrow/active1.png
AssetGenImage get active1 =>
const AssetGenImage('assets/images/spaceship/ramp/arrow/active1.png');
/// File path: assets/images/spaceship/ramp/arrow/active2.png
AssetGenImage get active2 =>
const AssetGenImage('assets/images/spaceship/ramp/arrow/active2.png');
/// File path: assets/images/spaceship/ramp/arrow/active3.png
AssetGenImage get active3 =>
const AssetGenImage('assets/images/spaceship/ramp/arrow/active3.png');
/// File path: assets/images/spaceship/ramp/arrow/active4.png
AssetGenImage get active4 =>
const AssetGenImage('assets/images/spaceship/ramp/arrow/active4.png');
/// File path: assets/images/spaceship/ramp/arrow/active5.png
AssetGenImage get active5 =>
const AssetGenImage('assets/images/spaceship/ramp/arrow/active5.png');
/// File path: assets/images/spaceship/ramp/arrow/inactive.png
AssetGenImage get inactive =>
const AssetGenImage('assets/images/spaceship/ramp/arrow/inactive.png');
}
class $AssetsImagesSparkyBumperAGen {
const $AssetsImagesSparkyBumperAGen();

@ -101,6 +101,8 @@ abstract class RenderPriority {
static const int spaceshipRampBackgroundRailing = _above + spaceshipRamp;
static const int spaceshipRampArrow = _above + spaceshipRamp;
static const int spaceshipRampForegroundRailing =
_above + ballOnSpaceshipRamp;

@ -4,6 +4,7 @@ import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball_components/gen/assets.gen.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets;
import 'package:pinball_flame/pinball_flame.dart';
@ -15,6 +16,15 @@ class SpaceshipRamp extends Forge2DBlueprint {
/// {@macro spaceship_ramp}
SpaceshipRamp();
/// [SpriteGroupComponent] representing the arrow that lights up.
@visibleForTesting
late final SpaceshipRampArrowSpriteComponent spaceshipRampArrow;
/// Forwards the sprite to the next [SpaceshipRampArrowSpriteState].
///
/// If the current state is the last one it cycles back to the initial state.
void progress() => spaceshipRampArrow.progress();
@override
void build(_) {
addAllContactCallback([
@ -23,20 +33,22 @@ class SpaceshipRamp extends Forge2DBlueprint {
final rightOpening = _SpaceshipRampOpening(
outsidePriority: RenderPriority.ballOnBoard,
rotation: math.pi,
rotation: -5 * math.pi / 180,
)
..initialPosition = Vector2(1.7, -19.8)
..initialPosition = Vector2(1.7, -19.12)
..layer = Layer.opening;
final leftOpening = _SpaceshipRampOpening(
outsideLayer: Layer.spaceship,
outsidePriority: RenderPriority.ballOnSpaceship,
rotation: math.pi,
rotation: -5 * math.pi / 180,
)
..initialPosition = Vector2(-13.7, -18.6)
..initialPosition = Vector2(-13.7, -19)
..layer = Layer.spaceshipEntranceRamp;
final spaceshipRamp = _SpaceshipRampBackground();
spaceshipRampArrow = SpaceshipRampArrowSpriteComponent();
final spaceshipRampBoardOpeningSprite =
_SpaceshipRampBoardOpeningSpriteComponent()
..position = Vector2(3.4, -39.5);
@ -52,15 +64,69 @@ class SpaceshipRamp extends Forge2DBlueprint {
baseRight,
_SpaceshipRampBackgroundRailingSpriteComponent(),
spaceshipRamp,
spaceshipRampArrow,
spaceshipRampForegroundRailing,
]);
}
}
/// Indicates the state of the arrow on the [SpaceshipRamp].
@visibleForTesting
enum SpaceshipRampArrowSpriteState {
/// Arrow with no dashes lit up.
inactive,
/// Arrow with 1 light lit up.
active1,
/// Arrow with 2 lights lit up.
active2,
/// Arrow with 3 lights lit up.
active3,
/// Arrow with 4 lights lit up.
active4,
/// Arrow with all 5 lights lit up.
active5,
}
extension on SpaceshipRampArrowSpriteState {
String get path {
switch (this) {
case SpaceshipRampArrowSpriteState.inactive:
return Assets.images.spaceship.ramp.arrow.inactive.keyName;
case SpaceshipRampArrowSpriteState.active1:
return Assets.images.spaceship.ramp.arrow.active1.keyName;
case SpaceshipRampArrowSpriteState.active2:
return Assets.images.spaceship.ramp.arrow.active2.keyName;
case SpaceshipRampArrowSpriteState.active3:
return Assets.images.spaceship.ramp.arrow.active3.keyName;
case SpaceshipRampArrowSpriteState.active4:
return Assets.images.spaceship.ramp.arrow.active4.keyName;
case SpaceshipRampArrowSpriteState.active5:
return Assets.images.spaceship.ramp.arrow.active5.keyName;
}
}
SpaceshipRampArrowSpriteState get next {
return SpaceshipRampArrowSpriteState
.values[(index + 1) % SpaceshipRampArrowSpriteState.values.length];
}
}
class _SpaceshipRampBackground extends BodyComponent
with InitialPosition, Layered {
_SpaceshipRampBackground() : super(priority: RenderPriority.spaceshipRamp) {
_SpaceshipRampBackground()
: super(
priority: RenderPriority.spaceshipRamp,
children: [
_SpaceshipRampBackgroundRampSpriteComponent(),
],
) {
layer = Layer.spaceshipEntranceRamp;
renderBody = false;
}
/// Width between walls of the ramp.
@ -112,30 +178,26 @@ class _SpaceshipRampBackground extends BodyComponent
return body;
}
@override
Future<void> onLoad() async {
await super.onLoad();
renderBody = false;
await add(_SpaceshipRampBackgroundRampSpriteComponent());
}
}
class _SpaceshipRampBackgroundRailingSpriteComponent extends SpriteComponent
with HasGameRef {
_SpaceshipRampBackgroundRailingSpriteComponent()
: super(priority: RenderPriority.spaceshipRampBackgroundRailing);
: super(
anchor: Anchor.center,
position: Vector2(-11.7, -54.3),
priority: RenderPriority.spaceshipRampBackgroundRailing,
);
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(
Assets.images.spaceship.ramp.railingBackground.keyName,
final sprite = Sprite(
gameRef.images.fromCache(
Assets.images.spaceship.ramp.railingBackground.keyName,
),
);
this.sprite = sprite;
size = sprite.originalSize / 10;
anchor = Anchor.center;
position = Vector2(-11.7, -54.3);
}
}
@ -144,13 +206,50 @@ class _SpaceshipRampBackgroundRampSpriteComponent extends SpriteComponent
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(
Assets.images.spaceship.ramp.main.keyName,
final sprite = Sprite(
gameRef.images.fromCache(
Assets.images.spaceship.ramp.main.keyName,
),
);
this.sprite = sprite;
size = sprite.originalSize / 10;
anchor = Anchor.center;
position = Vector2(-11.7, -53.6);
position = Vector2(-10.7, -53.6);
}
}
/// {@template spaceship_ramp_arrow_sprite_component}
/// An arrow inside [SpaceshipRamp].
///
/// Lights up a each dash whenever a [Ball] gets into [SpaceshipRamp].
/// {@endtemplate}
class SpaceshipRampArrowSpriteComponent
extends SpriteGroupComponent<SpaceshipRampArrowSpriteState>
with HasGameRef {
/// {@macro spaceship_ramp_arrow_sprite_component}
SpaceshipRampArrowSpriteComponent()
: super(
anchor: Anchor.center,
position: Vector2(-3.9, -56.5),
priority: RenderPriority.spaceshipRampArrow,
);
/// Changes arrow image to the next [Sprite].
void progress() => current = current?.next;
@override
Future<void> onLoad() async {
await super.onLoad();
final sprites = <SpaceshipRampArrowSpriteState, Sprite>{};
this.sprites = sprites;
for (final spriteState in SpaceshipRampArrowSpriteState.values) {
sprites[spriteState] = Sprite(
gameRef.images.fromCache(spriteState.path),
);
}
current = SpaceshipRampArrowSpriteState.inactive;
size = sprites[current]!.originalSize / 10;
}
}
@ -159,8 +258,10 @@ class _SpaceshipRampBoardOpeningSpriteComponent extends SpriteComponent
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(
Assets.images.spaceship.ramp.boardOpening.keyName,
final sprite = Sprite(
gameRef.images.fromCache(
Assets.images.spaceship.ramp.boardOpening.keyName,
),
);
this.sprite = sprite;
size = sprite.originalSize / 10;
@ -231,16 +332,22 @@ class _SpaceshipRampForegroundRailing extends BodyComponent
class _SpaceshipRampForegroundRailingSpriteComponent extends SpriteComponent
with HasGameRef {
_SpaceshipRampForegroundRailingSpriteComponent()
: super(
anchor: Anchor.center,
position: Vector2(-12.3, -52.5),
);
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(
Assets.images.spaceship.ramp.railingForeground.keyName,
final sprite = Sprite(
gameRef.images.fromCache(
Assets.images.spaceship.ramp.railingForeground.keyName,
),
);
this.sprite = sprite;
size = sprite.originalSize / 10;
anchor = Anchor.center;
position = Vector2(-12.3, -52.5);
}
}

@ -52,6 +52,7 @@ flutter:
- assets/images/spaceship/
- assets/images/spaceship/rail/
- assets/images/spaceship/ramp/
- assets/images/spaceship/ramp/arrow/
- assets/images/chrome_dino/
- assets/images/kicker/
- assets/images/plunger/

@ -2,11 +2,12 @@ import 'dart:async';
import 'package:flame/input.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
import 'package:sandbox/stories/ball/basic_ball_game.dart';
class SpaceshipRampGame extends BasicBallGame {
class SpaceshipRampGame extends BasicBallGame with KeyboardEvents {
SpaceshipRampGame()
: super(
color: Colors.blue,
@ -19,13 +20,45 @@ class SpaceshipRampGame extends BasicBallGame {
- Activate the "trace" parameter to overlay the body.
- Tap anywhere on the screen to spawn a ball into the game.
- Press space to progress arrow sprites.
''';
late final SpaceshipRamp _spaceshipRamp;
@override
Future<void> onLoad() async {
await super.onLoad();
await addFromBlueprint(SpaceshipRamp());
await images.loadAll([
Assets.images.spaceship.ramp.railingBackground.keyName,
Assets.images.spaceship.ramp.main.keyName,
Assets.images.spaceship.ramp.boardOpening.keyName,
Assets.images.spaceship.ramp.railingForeground.keyName,
Assets.images.spaceship.ramp.arrow.inactive.keyName,
Assets.images.spaceship.ramp.arrow.active1.keyName,
Assets.images.spaceship.ramp.arrow.active2.keyName,
Assets.images.spaceship.ramp.arrow.active3.keyName,
Assets.images.spaceship.ramp.arrow.active4.keyName,
Assets.images.spaceship.ramp.arrow.active5.keyName,
]);
_spaceshipRamp = SpaceshipRamp();
await addFromBlueprint(_spaceshipRamp);
camera.followVector2(Vector2(-12, -50));
await traceAllBodies();
}
@override
KeyEventResult onKeyEvent(
RawKeyEvent event,
Set<LogicalKeyboardKey> keysPressed,
) {
if (event is RawKeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.space) {
_spaceshipRamp.progress();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

@ -1,5 +1,6 @@
// ignore_for_file: cascade_invocations
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
@ -9,22 +10,197 @@ import 'package:pinball_flame/pinball_flame.dart';
import '../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.spaceship.ramp.boardOpening.keyName,
Assets.images.spaceship.ramp.railingForeground.keyName,
Assets.images.spaceship.ramp.railingBackground.keyName,
Assets.images.spaceship.ramp.main.keyName,
Assets.images.spaceship.ramp.arrow.inactive.keyName,
Assets.images.spaceship.ramp.arrow.active1.keyName,
Assets.images.spaceship.ramp.arrow.active2.keyName,
Assets.images.spaceship.ramp.arrow.active3.keyName,
Assets.images.spaceship.ramp.arrow.active4.keyName,
Assets.images.spaceship.ramp.arrow.active5.keyName,
];
final flameTester = FlameTester(() => TestGame(assets));
group('SpaceshipRamp', () {
final tester = FlameTester(TestGame.new);
tester.testGameWidget(
'renders correctly',
setUp: (game, tester) async {
await game.addFromBlueprint(SpaceshipRamp());
game.camera.followVector2(Vector2(-13, -50));
await game.ready();
},
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/spaceship-ramp.png'),
);
flameTester.test(
'loads correctly',
(game) async {
final spaceshipRamp = SpaceshipRamp();
await game.ensureAdd(spaceshipRamp);
expect(game.contains(spaceshipRamp), isTrue);
},
);
group('renders correctly', () {
final centerForSpaceshipRamp = Vector2(-13, -55);
flameTester.testGameWidget(
'inactive sprite',
setUp: (game, tester) async {
await game.images.loadAll(assets);
final spaceshipRamp = SpaceshipRamp();
await game.addFromBlueprint(spaceshipRamp);
await game.ready();
await tester.pump();
expect(
spaceshipRamp.spaceshipRampArrow.current,
SpaceshipRampArrowSpriteState.inactive,
);
game.camera.followVector2(centerForSpaceshipRamp);
},
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/spaceship_ramp/inactive.png'),
);
},
);
flameTester.testGameWidget(
'active1 sprite',
setUp: (game, tester) async {
await game.images.loadAll(assets);
final spaceshipRamp = SpaceshipRamp();
await game.addFromBlueprint(spaceshipRamp);
await game.ready();
spaceshipRamp.progress();
await tester.pump();
expect(
spaceshipRamp.spaceshipRampArrow.current,
SpaceshipRampArrowSpriteState.active1,
);
game.camera.followVector2(centerForSpaceshipRamp);
},
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/spaceship_ramp/active1.png'),
);
},
);
flameTester.testGameWidget(
'active2 sprite',
setUp: (game, tester) async {
await game.images.loadAll(assets);
final spaceshipRamp = SpaceshipRamp();
await game.addFromBlueprint(spaceshipRamp);
await game.ready();
spaceshipRamp
..progress()
..progress();
await tester.pump();
expect(
spaceshipRamp.spaceshipRampArrow.current,
SpaceshipRampArrowSpriteState.active2,
);
game.camera.followVector2(centerForSpaceshipRamp);
},
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/spaceship_ramp/active2.png'),
);
},
);
flameTester.testGameWidget(
'active3 sprite',
setUp: (game, tester) async {
await game.images.loadAll(assets);
final spaceshipRamp = SpaceshipRamp();
await game.addFromBlueprint(spaceshipRamp);
await game.ready();
spaceshipRamp
..progress()
..progress()
..progress();
await tester.pump();
expect(
spaceshipRamp.spaceshipRampArrow.current,
SpaceshipRampArrowSpriteState.active3,
);
game.camera.followVector2(centerForSpaceshipRamp);
},
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/spaceship_ramp/active3.png'),
);
},
);
flameTester.testGameWidget(
'active4 sprite',
setUp: (game, tester) async {
await game.images.loadAll(assets);
final spaceshipRamp = SpaceshipRamp();
await game.addFromBlueprint(spaceshipRamp);
await game.ready();
spaceshipRamp
..progress()
..progress()
..progress()
..progress();
await tester.pump();
expect(
spaceshipRamp.spaceshipRampArrow.current,
SpaceshipRampArrowSpriteState.active4,
);
game.camera.followVector2(centerForSpaceshipRamp);
},
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/spaceship_ramp/active4.png'),
);
},
);
flameTester.testGameWidget(
'active5 sprite',
setUp: (game, tester) async {
await game.images.loadAll(assets);
final spaceshipRamp = SpaceshipRamp();
await game.addFromBlueprint(spaceshipRamp);
await game.ready();
spaceshipRamp
..progress()
..progress()
..progress()
..progress()
..progress();
await tester.pump();
expect(
spaceshipRamp.spaceshipRampArrow.current,
SpaceshipRampArrowSpriteState.active5,
);
game.camera.followVector2(centerForSpaceshipRamp);
},
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/spaceship_ramp/active5.png'),
);
},
);
});
});
}

@ -85,14 +85,14 @@ void main() {
);
});
group('IncreasedMultiplier', () {
group('MultiplierIncreased', () {
blocTest<GameBloc, GameState>(
'increases multiplier '
'when game is not over',
build: GameBloc.new,
act: (bloc) => bloc
..add(const IncreasedMultiplier(increase: 1))
..add(const IncreasedMultiplier(increase: 1)),
..add(const MultiplierIncreased(increase: 1))
..add(const MultiplierIncreased(increase: 1)),
expect: () => [
const GameState(
score: 0,
@ -117,7 +117,7 @@ void main() {
for (var i = 0; i < bloc.state.balls; i++) {
bloc.add(const BallLost());
}
bloc.add(const IncreasedMultiplier(increase: 1));
bloc.add(const MultiplierIncreased(increase: 1));
},
expect: () => [
const GameState(
@ -142,7 +142,7 @@ void main() {
);
});
group('AppliedMultiplier', () {
group('MultiplierApplied', () {
blocTest<GameBloc, GameState>(
'apply multiplier to score',
build: GameBloc.new,
@ -153,7 +153,7 @@ void main() {
bonusHistory: [],
),
act: (bloc) {
bloc.add(const AppliedMultiplier());
bloc.add(const MultiplierApplied());
},
expect: () => [
const GameState(
@ -166,7 +166,7 @@ void main() {
);
});
group('ResetMultiplier', () {
group('MultiplierReset', () {
blocTest<GameBloc, GameState>(
'resets multiplier',
build: GameBloc.new,
@ -177,7 +177,7 @@ void main() {
bonusHistory: [],
),
act: (bloc) {
bloc.add(const ResetMultiplier());
bloc.add(const MultiplierReset());
},
expect: () => [
const GameState(

@ -41,51 +41,51 @@ void main() {
});
});
group('IncreasedMultiplier', () {
group('MultiplierIncreased', () {
test('can be instantiated', () {
expect(const IncreasedMultiplier(increase: 1), isNotNull);
expect(const MultiplierIncreased(increase: 1), isNotNull);
});
test('supports value equality', () {
expect(
IncreasedMultiplier(increase: 1),
equals(const IncreasedMultiplier(increase: 1)),
MultiplierIncreased(increase: 1),
equals(const MultiplierIncreased(increase: 1)),
);
expect(
const IncreasedMultiplier(increase: 1),
isNot(equals(const IncreasedMultiplier(increase: 2))),
const MultiplierIncreased(increase: 1),
isNot(equals(const MultiplierIncreased(increase: 2))),
);
});
test(
'throws AssertionError '
'when increase is smaller than 1', () {
expect(() => IncreasedMultiplier(increase: 0), throwsAssertionError);
expect(() => MultiplierIncreased(increase: 0), throwsAssertionError);
});
});
group('AppliedMultiplier', () {
group('MultiplierApplied', () {
test('can be instantiated', () {
expect(const AppliedMultiplier(), isNotNull);
expect(const MultiplierApplied(), isNotNull);
});
test('supports value equality', () {
expect(
AppliedMultiplier(),
equals(const AppliedMultiplier()),
MultiplierApplied(),
equals(const MultiplierApplied()),
);
});
});
group('ResetMultiplier', () {
group('MultiplierReset', () {
test('can be instantiated', () {
expect(const ResetMultiplier(), isNotNull);
expect(const MultiplierReset(), isNotNull);
});
test('supports value equality', () {
expect(
ResetMultiplier(),
equals(const ResetMultiplier()),
MultiplierReset(),
equals(const MultiplierReset()),
);
});
});

@ -1,110 +0,0 @@
// ignore_for_file: cascade_invocations
import 'package:flame/components.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
void main() {
group('ScoreEffectController', () {
late ScoreEffectController controller;
late PinballGame game;
setUpAll(() {
registerFallbackValue(Component());
});
setUp(() {
game = MockPinballGame();
when(() => game.add(any())).thenAnswer((_) async {});
controller = ScoreEffectController(game);
});
group('listenWhen', () {
test('returns true when the user has earned points', () {
const previous = GameState.initial();
const current = GameState(
score: 10,
multiplier: 1,
balls: 3,
bonusHistory: [],
);
expect(controller.listenWhen(previous, current), isTrue);
});
test(
'returns true when the user has earned points and there was no '
'previous state',
() {
const current = GameState(
score: 10,
multiplier: 1,
balls: 3,
bonusHistory: [],
);
expect(controller.listenWhen(null, current), isTrue);
},
);
test(
'returns false when no points were earned',
() {
const current = GameState.initial();
const previous = GameState.initial();
expect(controller.listenWhen(previous, current), isFalse);
},
);
});
group('onNewState', () {
test(
'adds a ScoreText with the correct score for the '
'first time',
() {
const state = GameState(
score: 10,
multiplier: 1,
balls: 3,
bonusHistory: [],
);
controller.onNewState(state);
final effect =
verify(() => game.add(captureAny())).captured.first as ScoreText;
expect(effect.text, equals('10'));
},
);
test('adds a ScoreTextEffect with the correct score', () {
controller.onNewState(
const GameState(
score: 10,
multiplier: 1,
balls: 3,
bonusHistory: [],
),
);
controller.onNewState(
const GameState(
score: 14,
multiplier: 1,
balls: 3,
bonusHistory: [],
),
);
final effect =
verify(() => game.add(captureAny())).captured.last as ScoreText;
expect(effect.text, equals('4'));
});
});
});
}

@ -28,9 +28,13 @@ void main() {
setUp(() {
game = MockPinballGame();
bloc = MockGameBloc();
ball = MockBall();
audio = MockPinballAudio();
fakeScorePoints = FakeScorePoints();
ball = MockBall();
final ballBody = MockBody();
when(() => ball.body).thenReturn(ballBody);
when(() => ballBody.position).thenReturn(Vector2.all(4));
});
setUpAll(() {
@ -73,6 +77,29 @@ void main() {
verify(audio.score).called(1);
},
);
test(
"adds a ScoreText component at Ball's position",
() {
when(game.read<GameBloc>).thenReturn(bloc);
when(() => game.audio).thenReturn(audio);
BallScorePointsCallback(game).begin(
ball,
fakeScorePoints,
FakeContact(),
);
verify(
() => game.add(
ScoreText(
text: fakeScorePoints.points.toString(),
position: ball.body.position,
),
),
).called(1);
},
);
});
});
}

@ -33,6 +33,16 @@ void main() {
Assets.images.sparky.bumper.b.inactive.keyName,
Assets.images.sparky.bumper.c.active.keyName,
Assets.images.sparky.bumper.c.inactive.keyName,
Assets.images.spaceship.ramp.boardOpening.keyName,
Assets.images.spaceship.ramp.railingForeground.keyName,
Assets.images.spaceship.ramp.railingBackground.keyName,
Assets.images.spaceship.ramp.main.keyName,
Assets.images.spaceship.ramp.arrow.inactive.keyName,
Assets.images.spaceship.ramp.arrow.active1.keyName,
Assets.images.spaceship.ramp.arrow.active2.keyName,
Assets.images.spaceship.ramp.arrow.active3.keyName,
Assets.images.spaceship.ramp.arrow.active4.keyName,
Assets.images.spaceship.ramp.arrow.active5.keyName,
];
final flameTester = FlameTester(() => PinballTestGame(assets));
final debugModeFlameTester = FlameTester(() => DebugPinballTestGame(assets));

Loading…
Cancel
Save