feat: add dino game bonus (#301)

* feat: connect dino bonus

* fix: remove ball on spit

* refactor: move logic to cubit

* chore: update test cases
pull/307/head
Allison Ryan 3 years ago committed by GitHub
parent 30cb1f9daf
commit 9784091f84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,7 +4,7 @@ export 'camera_controller.dart';
export 'controlled_ball.dart';
export 'controlled_flipper.dart';
export 'controlled_plunger.dart';
export 'dino_desert.dart';
export 'dino_desert/dino_desert.dart';
export 'drain.dart';
export 'flutter_forest/flutter_forest.dart';
export 'game_flow_controller.dart';

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

@ -0,0 +1,24 @@
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';
/// Adds a [GameBonus.dinoChomp] when a [Ball] is chomped by the [ChromeDino].
class ChromeDinoBonusBehavior extends Component
with HasGameRef<PinballGame>, ParentIsA<DinoDesert> {
@override
void onMount() {
super.onMount();
final chromeDino = parent.firstChild<ChromeDino>()!;
// TODO(alestiago): Refactor subscription management once the following is
// merged:
// https://github.com/flame-engine/flame/pull/1538
chromeDino.bloc.stream.listen((state) {
final listenWhen = state.status == ChromeDinoStatus.chomping;
if (!listenWhen) return;
gameRef.read<GameBloc>().add(const BonusActivated(GameBonus.dinoChomp));
});
}
}

@ -1,11 +1,13 @@
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball/game/components/dino_desert/behaviors/behaviors.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
/// {@template dino_desert}
/// Area located next to the [Launcher] containing the [ChromeDino] and
/// [DinoWalls].
/// Area located next to the [Launcher] containing the [ChromeDino],
/// [DinoWalls], and the [Slingshots].
/// {@endtemplate}
class DinoDesert extends Component {
/// {@macro dino_desert}
@ -21,8 +23,15 @@ class DinoDesert extends Component {
_BarrierBehindDino(),
DinoWalls(),
Slingshots(),
ChromeDinoBonusBehavior(),
],
);
/// Creates [DinoDesert] without any children.
///
/// This can be used for testing [DinoDesert]'s behaviors in isolation.
@visibleForTesting
DinoDesert.test();
}
class _BarrierBehindDino extends BodyComponent {

@ -18,10 +18,17 @@ class ChromeDinoCubit extends Cubit<ChromeDinoState> {
}
void onChomp(Ball ball) {
if (ball != state.ball) {
emit(state.copyWith(status: ChromeDinoStatus.chomping, ball: ball));
}
}
void onSpit() {
emit(state.copyWith(status: ChromeDinoStatus.idle));
emit(
ChromeDinoState(
status: ChromeDinoStatus.idle,
isMouthOpen: state.isMouthOpen,
),
);
}
}

@ -36,7 +36,8 @@ void main() {
);
blocTest<ChromeDinoCubit, ChromeDinoState>(
'onChomp emits ChromeDinoStatus.chomping and chomped ball',
'onChomp emits ChromeDinoStatus.chomping and chomped ball '
'when the ball is not in the mouth',
build: ChromeDinoCubit.new,
act: (bloc) => bloc.onChomp(ball),
expect: () => [
@ -55,7 +56,15 @@ void main() {
);
blocTest<ChromeDinoCubit, ChromeDinoState>(
'onSpit emits ChromeDinoStatus.idle',
'onChomp emits nothing when the ball is already in the mouth',
build: ChromeDinoCubit.new,
seed: () => const ChromeDinoState.inital().copyWith(ball: ball),
act: (bloc) => bloc.onChomp(ball),
expect: () => <ChromeDinoState>[],
);
blocTest<ChromeDinoCubit, ChromeDinoState>(
'onSpit emits ChromeDinoStatus.idle and removes ball',
build: ChromeDinoCubit.new,
act: (bloc) => bloc.onSpit(),
expect: () => [
@ -63,6 +72,10 @@ void main() {
(state) => state.status,
'status',
ChromeDinoStatus.idle,
)..having(
(state) => state.ball,
'ball',
null,
)
],
);

@ -0,0 +1,63 @@
// ignore_for_file: cascade_invocations
import 'package:bloc_test/bloc_test.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/components/dino_desert/behaviors/behaviors.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.dino.animatronic.head.keyName,
Assets.images.dino.animatronic.mouth.keyName,
Assets.images.dino.topWall.keyName,
Assets.images.dino.bottomWall.keyName,
Assets.images.slingshot.upper.keyName,
Assets.images.slingshot.lower.keyName,
];
group('ChromeDinoBonusBehavior', () {
late GameBloc gameBloc;
setUp(() {
gameBloc = MockGameBloc();
whenListen(
gameBloc,
const Stream<GameState>.empty(),
initialState: const GameState.initial(),
);
});
final flameBlocTester = FlameBlocTester<PinballGame, GameBloc>(
gameBuilder: EmptyPinballTestGame.new,
blocBuilder: () => gameBloc,
assets: assets,
);
flameBlocTester.testGameWidget(
'adds GameBonus.dinoChomp to the game '
'when ChromeDinoStatus.chomping is emitted',
setUp: (game, tester) async {
final behavior = ChromeDinoBonusBehavior();
final parent = DinoDesert.test();
final chromeDino = ChromeDino();
await parent.add(chromeDino);
await game.ensureAdd(parent);
await parent.ensureAdd(behavior);
chromeDino.bloc.onChomp(MockBall());
await tester.pump();
verify(
() => gameBloc.add(const BonusActivated(GameBonus.dinoChomp)),
).called(1);
},
);
});
}

@ -2,10 +2,11 @@
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/game/components/dino_desert/behaviors/behaviors.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
import '../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
@ -63,8 +64,9 @@ void main() {
);
});
group('adds', () {
flameTester.test(
'adds ScoringBehavior to ChromeDino',
'ScoringBehavior to ChromeDino',
(game) async {
await game.ensureAdd(DinoDesert());
@ -75,5 +77,15 @@ void main() {
);
},
);
flameTester.test('a ChromeDinoBonusBehavior', (game) async {
final dinoDesert = DinoDesert();
await game.ensureAdd(dinoDesert);
expect(
dinoDesert.children.whereType<ChromeDinoBonusBehavior>().single,
isNotNull,
);
});
});
});
}
Loading…
Cancel
Save