diff --git a/lib/game/components/sparky_fire_zone.dart b/lib/game/components/sparky_fire_zone.dart index 9d88f0f5..ee8da614 100644 --- a/lib/game/components/sparky_fire_zone.dart +++ b/lib/game/components/sparky_fire_zone.dart @@ -1,21 +1,67 @@ // ignore_for_file: avoid_renaming_method_parameters import 'package:flame/components.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter/material.dart'; import 'package:pinball/flame/flame.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -// TODO(ruimiguel): create and add SparkyFireZone component here in other PR. +/// {@template sparky_fire_zone} +/// Area positioned at the top left of the [Board] where the [Ball] +/// can bounce off [SparkyBumper]s. +/// +/// When a [Ball] hits [SparkyBumper]s, they toggle between activated and +/// deactivated states. +/// {@endtemplate} +class SparkyFireZone extends Component with HasGameRef { + /// {@macro sparky_fire_zone} + SparkyFireZone(); + + @override + Future onLoad() async { + await super.onLoad(); + + gameRef.addContactCallback(_ControlledSparkyBumperBallContactCallback()); -// TODO(ruimiguel): make private and remove ignore once SparkyFireZone is done -// ignore: public_member_api_docs + final lowerLeftBumper = ControlledSparkyBumper.a() + ..initialPosition = Vector2(-23.15, 41.65); + final upperLeftBumper = ControlledSparkyBumper.b() + ..initialPosition = Vector2(-21.25, 58.15); + final rightBumper = ControlledSparkyBumper.c() + ..initialPosition = Vector2(-3.56, 53.051); + + await addAll([ + lowerLeftBumper, + upperLeftBumper, + rightBumper, + ]); + } +} + +/// {@template controlled_sparky_bumper} +/// [SparkyBumper] with [_SparkyBumperController] attached. +/// {@endtemplate} +@visibleForTesting class ControlledSparkyBumper extends SparkyBumper - with Controls<_SparkyBumperController> { - // TODO(ruimiguel): make private and remove ignore once SparkyFireZone is done - // ignore: public_member_api_docs - ControlledSparkyBumper() : super.a() { + with Controls<_SparkyBumperController>, ScorePoints { + ///{@macro controlled_sparky_bumper} + ControlledSparkyBumper.a() : super.a() { + controller = _SparkyBumperController(this); + } + + ///{@macro controlled_sparky_bumper} + ControlledSparkyBumper.b() : super.b() { + controller = _SparkyBumperController(this); + } + + ///{@macro controlled_sparky_bumper} + ControlledSparkyBumper.c() : super.c() { controller = _SparkyBumperController(this); } + + @override + int get points => 20; } /// {@template sparky_bumper_controller} @@ -42,3 +88,16 @@ class _SparkyBumperController extends ComponentController isActivated = !isActivated; } } + +/// Listens when a [Ball] bounces bounces against a [SparkyBumper]. +class _ControlledSparkyBumperBallContactCallback + extends ContactCallback, Ball> { + @override + void begin( + Controls<_SparkyBumperController> controlledSparkyBumper, + Ball _, + Contact __, + ) { + controlledSparkyBumper.controller.hit(); + } +} diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index 49992653..27a56743 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -52,6 +52,7 @@ class PinballGame extends Forge2DGame await add(plunger); unawaited(add(Board())); + unawaited(add(SparkyFireZone())); unawaited(addFromBlueprint(Slingshots())); unawaited(addFromBlueprint(DinoWalls())); unawaited(_addBonusWord()); diff --git a/packages/pinball_components/lib/src/components/launch_ramp.dart b/packages/pinball_components/lib/src/components/launch_ramp.dart index 2eea7a91..deaa3941 100644 --- a/packages/pinball_components/lib/src/components/launch_ramp.dart +++ b/packages/pinball_components/lib/src/components/launch_ramp.dart @@ -11,6 +11,9 @@ import 'package:pinball_components/pinball_components.dart'; /// [_LaunchRampForegroundRailing]. /// {@endtemplate} class LaunchRamp extends Forge2DBlueprint { + /// Base priority for [Ball] while inside [LaunchRamp]. + static const ballPriorityInsideRamp = 0; + @override void build(_) { addAllContactCallback([ @@ -40,7 +43,10 @@ class LaunchRamp extends Forge2DBlueprint { /// {@endtemplate} class _LaunchRampBase extends BodyComponent with InitialPosition, Layered { /// {@macro launch_ramp_base} - _LaunchRampBase() : super(priority: -1) { + _LaunchRampBase() + : super( + priority: LaunchRamp.ballPriorityInsideRamp - 1, + ) { layer = Layer.launcher; } @@ -143,7 +149,10 @@ class _LaunchRampBaseSpriteComponent extends SpriteComponent with HasGameRef { class _LaunchRampForegroundRailing extends BodyComponent with InitialPosition, Layered { /// {@macro launch_ramp_foreground_railing} - _LaunchRampForegroundRailing() : super(priority: 1) { + _LaunchRampForegroundRailing() + : super( + priority: LaunchRamp.ballPriorityInsideRamp + 1, + ) { layer = Layer.launcher; } @@ -227,7 +236,7 @@ class _LaunchRampExit extends RampOpening { super( insideLayer: Layer.launcher, orientation: RampOrientation.down, - insidePriority: 3, + insidePriority: LaunchRamp.ballPriorityInsideRamp, ); final double _rotation; diff --git a/packages/pinball_components/lib/src/components/spaceship.dart b/packages/pinball_components/lib/src/components/spaceship.dart index 10144eef..6643a53a 100644 --- a/packages/pinball_components/lib/src/components/spaceship.dart +++ b/packages/pinball_components/lib/src/components/spaceship.dart @@ -37,7 +37,7 @@ class Spaceship extends Forge2DBlueprint { AndroidHead()..initialPosition = position, SpaceshipHole( outsideLayer: Layer.spaceshipExitRail, - outsidePriority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail, + outsidePriority: SpaceshipRail.ballPriorityInsideRail, )..initialPosition = position - Vector2(5.2, 4.8), SpaceshipHole()..initialPosition = position - Vector2(-7.2, 0.8), SpaceshipWall()..initialPosition = position, diff --git a/packages/pinball_components/lib/src/components/spaceship_rail.dart b/packages/pinball_components/lib/src/components/spaceship_rail.dart index 2cc8bccc..b63e401a 100644 --- a/packages/pinball_components/lib/src/components/spaceship_rail.dart +++ b/packages/pinball_components/lib/src/components/spaceship_rail.dart @@ -14,8 +14,8 @@ class SpaceshipRail extends Forge2DBlueprint { /// {@macro spaceship_rail} SpaceshipRail(); - /// Base priority for ball while be in [_SpaceshipRailRamp]. - static const ballPriorityWhenOnSpaceshipRail = 2; + /// Base priority for [Ball] while inside [SpaceshipRail]. + static const ballPriorityInsideRail = 2; @override void build(_) { @@ -45,9 +45,8 @@ class SpaceshipRail extends Forge2DBlueprint { class _SpaceshipRailRamp extends BodyComponent with InitialPosition, Layered { _SpaceshipRailRamp() : super( - priority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail - 1, + priority: SpaceshipRail.ballPriorityInsideRail - 1, ) { - renderBody = false; layer = Layer.spaceshipExitRail; } @@ -139,6 +138,8 @@ class _SpaceshipRailRamp extends BodyComponent with InitialPosition, Layered { @override Future onLoad() async { await super.onLoad(); + renderBody = false; + await add(_SpaceshipRailRampSpriteComponent()); } } @@ -161,11 +162,7 @@ class _SpaceshipRailRampSpriteComponent extends SpriteComponent class _SpaceshipRailForeground extends SpriteComponent with HasGameRef { _SpaceshipRailForeground() - : super( - anchor: Anchor.center, - position: Vector2(-28.5, 19.7), - priority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail + 1, - ); + : super(priority: SpaceshipRail.ballPriorityInsideRail + 1); @override Future onLoad() async { @@ -176,6 +173,8 @@ class _SpaceshipRailForeground extends SpriteComponent with HasGameRef { ); this.sprite = sprite; size = sprite.originalSize / 10; + anchor = Anchor.center; + position = Vector2(-28.5, 19.7); } } @@ -183,7 +182,7 @@ class _SpaceshipRailForeground extends SpriteComponent with HasGameRef { class _SpaceshipRailBase extends BodyComponent with InitialPosition, Layered { _SpaceshipRailBase({required this.radius}) : super( - priority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail + 1, + priority: SpaceshipRail.ballPriorityInsideRail + 1, ) { renderBody = false; layer = Layer.board; @@ -213,9 +212,9 @@ class SpaceshipRailExit extends RampOpening { /// {@macro spaceship_rail_exit} SpaceshipRailExit() : super( - insideLayer: Layer.spaceshipExitRail, orientation: RampOrientation.down, - insidePriority: 3, + insideLayer: Layer.spaceshipExitRail, + insidePriority: SpaceshipRail.ballPriorityInsideRail, ) { renderBody = false; layer = Layer.spaceshipExitRail; @@ -224,10 +223,10 @@ class SpaceshipRailExit extends RampOpening { @override Shape get shape { return ArcShape( - center: Vector2(-28, -19), + center: Vector2(-29, -19), arcRadius: 2.5, angle: math.pi * 0.4, - rotation: -0.16, + rotation: 0.26, ); } } diff --git a/packages/pinball_components/lib/src/components/spaceship_ramp.dart b/packages/pinball_components/lib/src/components/spaceship_ramp.dart index 773b0441..452d101e 100644 --- a/packages/pinball_components/lib/src/components/spaceship_ramp.dart +++ b/packages/pinball_components/lib/src/components/spaceship_ramp.dart @@ -184,8 +184,6 @@ class _SpaceshipRampForegroundRailing extends BodyComponent @override Body createBody() { - renderBody = false; - final bodyDef = BodyDef() ..userData = this ..position = initialPosition; @@ -199,11 +197,13 @@ class _SpaceshipRampForegroundRailing extends BodyComponent @override Future onLoad() async { await super.onLoad(); - await add(_SpaceshipRampForegroundRalingSpriteComponent()); + renderBody = false; + + await add(_SpaceshipRampForegroundRailingSpriteComponent()); } } -class _SpaceshipRampForegroundRalingSpriteComponent extends SpriteComponent +class _SpaceshipRampForegroundRailingSpriteComponent extends SpriteComponent with HasGameRef { @override Future onLoad() async { @@ -221,13 +221,12 @@ class _SpaceshipRampForegroundRalingSpriteComponent extends SpriteComponent /// Represents the ground right base of the [SpaceshipRamp]. class _SpaceshipRampBase extends BodyComponent with InitialPosition, Layered { _SpaceshipRampBase() { + renderBody = false; layer = Layer.board; } @override Body createBody() { - renderBody = false; - const baseWidth = 6; final baseShape = BezierCurveShape( controlPoints: [ @@ -266,7 +265,9 @@ class _SpaceshipRampOpening extends RampOpening { orientation: RampOrientation.down, insidePriority: SpaceshipRamp.ballPriorityInsideRamp, outsidePriority: outsidePriority, - ); + ) { + renderBody = false; + } final double _rotation; @@ -274,7 +275,6 @@ class _SpaceshipRampOpening extends RampOpening { @override Shape get shape { - renderBody = false; return PolygonShape() ..setAsBox( _size.x, diff --git a/packages/pinball_components/sandbox/lib/main.dart b/packages/pinball_components/sandbox/lib/main.dart index 983a3450..b65945a2 100644 --- a/packages/pinball_components/sandbox/lib/main.dart +++ b/packages/pinball_components/sandbox/lib/main.dart @@ -26,5 +26,8 @@ void main() { addZoomStories(dashbook); addBoundariesStories(dashbook); addGoogleWordStories(dashbook); + addSpaceshipRampStories(dashbook); + addSpaceshipRailStories(dashbook); + addLaunchRampStories(dashbook); runApp(dashbook); } diff --git a/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart b/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart index 40358682..4fbeae1b 100644 --- a/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart @@ -4,7 +4,11 @@ import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/common/common.dart'; class BasicBallGame extends BasicGame with TapDetector, Traceable { - BasicBallGame({required this.color}); + BasicBallGame({ + required this.color, + this.ballPriority = 0, + this.ballLayer = Layer.all, + }); static const info = ''' Shows how a Ball works. @@ -13,11 +17,16 @@ class BasicBallGame extends BasicGame with TapDetector, Traceable { '''; final Color color; + final int ballPriority; + final Layer ballLayer; @override void onTapUp(TapUpInfo info) { add( - Ball(baseColor: color)..initialPosition = info.eventPosition.game, + Ball(baseColor: color) + ..initialPosition = info.eventPosition.game + ..layer = ballLayer + ..priority = ballPriority, ); traceAllBodies(); } diff --git a/packages/pinball_components/sandbox/lib/stories/launch_ramp/launch_ramp_game.dart b/packages/pinball_components/sandbox/lib/stories/launch_ramp/launch_ramp_game.dart new file mode 100644 index 00000000..5258de86 --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/launch_ramp/launch_ramp_game.dart @@ -0,0 +1,36 @@ +import 'dart:async'; + +import 'package:flame/input.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:sandbox/stories/ball/basic_ball_game.dart'; + +class LaunchRampGame extends BasicBallGame { + LaunchRampGame() + : super( + color: Colors.blue, + ballPriority: LaunchRamp.ballPriorityInsideRamp, + ballLayer: Layer.launcher, + ); + + static const info = ''' + Shows how LaunchRamp are rendered. + + - Activate the "trace" parameter to overlay the body. + - Tap anywhere on the screen to spawn a ball into the game. +'''; + + @override + Future onLoad() async { + await super.onLoad(); + + camera + ..followVector2(Vector2(0, 0)) + ..zoom = 7.5; + + final launchRamp = LaunchRamp(); + unawaited(addFromBlueprint(launchRamp)); + + await traceAllBodies(); + } +} diff --git a/packages/pinball_components/sandbox/lib/stories/launch_ramp/stories.dart b/packages/pinball_components/sandbox/lib/stories/launch_ramp/stories.dart new file mode 100644 index 00000000..083a4584 --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/launch_ramp/stories.dart @@ -0,0 +1,15 @@ +import 'package:dashbook/dashbook.dart'; +import 'package:flame/game.dart'; +import 'package:sandbox/common/common.dart'; +import 'package:sandbox/stories/launch_ramp/launch_ramp_game.dart'; + +void addLaunchRampStories(Dashbook dashbook) { + dashbook.storiesOf('LaunchRamp').add( + 'Basic', + (context) => GameWidget( + game: LaunchRampGame()..trace = context.boolProperty('Trace', true), + ), + codeLink: buildSourceLink('launch_ramp/basic.dart'), + info: LaunchRampGame.info, + ); +} diff --git a/packages/pinball_components/sandbox/lib/stories/spaceship_rail/spaceship_rail_game.dart b/packages/pinball_components/sandbox/lib/stories/spaceship_rail/spaceship_rail_game.dart new file mode 100644 index 00000000..cef04304 --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/spaceship_rail/spaceship_rail_game.dart @@ -0,0 +1,34 @@ +import 'dart:async'; + +import 'package:flame/input.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:sandbox/stories/ball/basic_ball_game.dart'; + +class SpaceshipRailGame extends BasicBallGame { + SpaceshipRailGame() + : super( + color: Colors.blue, + ballPriority: SpaceshipRail.ballPriorityInsideRail, + ballLayer: Layer.spaceshipExitRail, + ); + + static const info = ''' + Shows how SpaceshipRail are rendered. + + - Activate the "trace" parameter to overlay the body. + - Tap anywhere on the screen to spawn a ball into the game. +'''; + + @override + Future onLoad() async { + await super.onLoad(); + + camera.followVector2(Vector2(-30, -10)); + + final spaceshipRail = SpaceshipRail(); + unawaited(addFromBlueprint(spaceshipRail)); + + await traceAllBodies(); + } +} diff --git a/packages/pinball_components/sandbox/lib/stories/spaceship_rail/stories.dart b/packages/pinball_components/sandbox/lib/stories/spaceship_rail/stories.dart new file mode 100644 index 00000000..e69ed1db --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/spaceship_rail/stories.dart @@ -0,0 +1,16 @@ +import 'package:dashbook/dashbook.dart'; +import 'package:flame/game.dart'; +import 'package:sandbox/common/common.dart'; +import 'package:sandbox/stories/spaceship_rail/spaceship_rail_game.dart'; + +void addSpaceshipRailStories(Dashbook dashbook) { + dashbook.storiesOf('SpaceshipRail').add( + 'Basic', + (context) => GameWidget( + game: SpaceshipRailGame() + ..trace = context.boolProperty('Trace', true), + ), + codeLink: buildSourceLink('spaceship_rail/basic.dart'), + info: SpaceshipRailGame.info, + ); +} diff --git a/packages/pinball_components/sandbox/lib/stories/spaceship_ramp/spaceship_ramp_game.dart b/packages/pinball_components/sandbox/lib/stories/spaceship_ramp/spaceship_ramp_game.dart new file mode 100644 index 00000000..e3850da3 --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/spaceship_ramp/spaceship_ramp_game.dart @@ -0,0 +1,34 @@ +import 'dart:async'; + +import 'package:flame/input.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:sandbox/stories/ball/basic_ball_game.dart'; + +class SpaceshipRampGame extends BasicBallGame { + SpaceshipRampGame() + : super( + color: Colors.blue, + ballPriority: SpaceshipRamp.ballPriorityInsideRamp, + ballLayer: Layer.spaceshipEntranceRamp, + ); + + static const info = ''' + Shows how SpaceshipRamp are rendered. + + - Activate the "trace" parameter to overlay the body. + - Tap anywhere on the screen to spawn a ball into the game. +'''; + + @override + Future onLoad() async { + await super.onLoad(); + + camera.followVector2(Vector2(-10, -20)); + + final spaceshipRamp = SpaceshipRamp(); + unawaited(addFromBlueprint(spaceshipRamp)); + + await traceAllBodies(); + } +} diff --git a/packages/pinball_components/sandbox/lib/stories/spaceship_ramp/stories.dart b/packages/pinball_components/sandbox/lib/stories/spaceship_ramp/stories.dart new file mode 100644 index 00000000..f0aeadff --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/spaceship_ramp/stories.dart @@ -0,0 +1,16 @@ +import 'package:dashbook/dashbook.dart'; +import 'package:flame/game.dart'; +import 'package:sandbox/common/common.dart'; +import 'package:sandbox/stories/spaceship_ramp/spaceship_ramp_game.dart'; + +void addSpaceshipRampStories(Dashbook dashbook) { + dashbook.storiesOf('SpaceshipRamp').add( + 'Basic', + (context) => GameWidget( + game: SpaceshipRampGame() + ..trace = context.boolProperty('Trace', true), + ), + codeLink: buildSourceLink('spaceship_ramp/basic.dart'), + info: SpaceshipRampGame.info, + ); +} diff --git a/packages/pinball_components/sandbox/lib/stories/stories.dart b/packages/pinball_components/sandbox/lib/stories/stories.dart index 4d52a7c7..4ed179bc 100644 --- a/packages/pinball_components/sandbox/lib/stories/stories.dart +++ b/packages/pinball_components/sandbox/lib/stories/stories.dart @@ -6,8 +6,11 @@ export 'effects/stories.dart'; export 'flipper/stories.dart'; export 'flutter_forest/stories.dart'; export 'google_word/stories.dart'; +export 'launch_ramp/stories.dart'; export 'layer/stories.dart'; export 'slingshot/stories.dart'; export 'spaceship/stories.dart'; +export 'spaceship_rail/stories.dart'; +export 'spaceship_ramp/stories.dart'; export 'sparky_bumper/stories.dart'; export 'zoom/stories.dart'; diff --git a/test/game/components/sparky_fire_zone_test.dart b/test/game/components/sparky_fire_zone_test.dart index dceaa9cc..da8d8404 100644 --- a/test/game/components/sparky_fire_zone_test.dart +++ b/test/game/components/sparky_fire_zone_test.dart @@ -1,8 +1,13 @@ // ignore_for_file: cascade_invocations +import 'dart:ui'; + +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/game.dart'; +import 'package:pinball_components/pinball_components.dart'; import '../../helpers/helpers.dart'; @@ -11,13 +16,57 @@ void main() { final flameTester = FlameTester(EmptyPinballGameTest.new); group('SparkyFireZone', () { + flameTester.test( + 'loads correctly', + (game) async { + await game.ready(); + final sparkyFireZone = SparkyFireZone(); + await game.ensureAdd(sparkyFireZone); + + expect(game.contains(sparkyFireZone), isTrue); + }, + ); + + group('loads', () { + flameTester.test( + 'three SparkyBumper', + (game) async { + await game.ready(); + final sparkyFireZone = SparkyFireZone(); + await game.ensureAdd(sparkyFireZone); + + expect( + sparkyFireZone.descendants().whereType().length, + equals(3), + ); + }, + ); + }); + group('bumpers', () { late ControlledSparkyBumper controlledSparkyBumper; + late Ball ball; + late GameBloc gameBloc; + + setUp(() { + ball = Ball(baseColor: const Color(0xFF00FFFF)); + gameBloc = MockGameBloc(); + whenListen( + gameBloc, + const Stream.empty(), + initialState: const GameState.initial(), + ); + }); + + final flameBlocTester = FlameBlocTester( + gameBuilder: EmptyPinballGameTest.new, + blocBuilder: () => gameBloc, + ); flameTester.testGameWidget( 'activate when deactivated bumper is hit', setUp: (game, tester) async { - controlledSparkyBumper = ControlledSparkyBumper(); + controlledSparkyBumper = ControlledSparkyBumper.a(); await game.ensureAdd(controlledSparkyBumper); controlledSparkyBumper.controller.hit(); @@ -30,7 +79,7 @@ void main() { flameTester.testGameWidget( 'deactivate when activated bumper is hit', setUp: (game, tester) async { - controlledSparkyBumper = ControlledSparkyBumper(); + controlledSparkyBumper = ControlledSparkyBumper.a(); await game.ensureAdd(controlledSparkyBumper); controlledSparkyBumper.controller.hit(); @@ -40,6 +89,27 @@ void main() { expect(controlledSparkyBumper.controller.isActivated, isFalse); }, ); + + flameBlocTester.testGameWidget( + 'add Scored event', + setUp: (game, tester) async { + final sparkyFireZone = SparkyFireZone(); + await game.ensureAdd(sparkyFireZone); + await game.ensureAdd(ball); + game.addContactCallback(BallScorePointsCallback(game)); + + final bumpers = sparkyFireZone.descendants().whereType(); + + for (final bumper in bumpers) { + beginContact(game, bumper, ball); + verify( + () => gameBloc.add( + Scored(points: bumper.points), + ), + ).called(1); + } + }, + ); }); }); } diff --git a/test/game/pinball_game_test.dart b/test/game/pinball_game_test.dart index d83bb396..2dfd5d76 100644 --- a/test/game/pinball_game_test.dart +++ b/test/game/pinball_game_test.dart @@ -62,6 +62,14 @@ void main() { ); }); + flameTester.test( + 'one SparkyFireZone', + (game) async { + await game.ready(); + expect(game.children.whereType().length, equals(1)); + }, + ); + group('controller', () { // TODO(alestiago): Write test to be controller agnostic. group('listenWhen', () {