diff --git a/assets/images/components/sauce.png b/assets/images/components/sauce.png deleted file mode 100644 index 743a920a..00000000 Binary files a/assets/images/components/sauce.png and /dev/null differ diff --git a/lib/flame/blueprint.dart b/lib/flame/blueprint.dart index d536d650..57af7d6d 100644 --- a/lib/flame/blueprint.dart +++ b/lib/flame/blueprint.dart @@ -14,6 +14,8 @@ const _attachedErrorMessage = "Can't add to attached Blueprints"; /// the [FlameGame] level. abstract class Blueprint { final List _components = []; + final List _blueprints = []; + bool _isAttached = false; /// Called before the the [Component]s managed @@ -25,7 +27,10 @@ abstract class Blueprint { @mustCallSuper Future attach(T game) async { build(game); - await game.addAll(_components); + await Future.wait([ + game.addAll(_components), + ..._blueprints.map(game.addFromBlueprint).toList(), + ]); _isAttached = true; } @@ -41,8 +46,23 @@ abstract class Blueprint { _components.add(component); } + /// Adds a list of [Blueprint]s to this blueprint. + void addAllBlueprints(List blueprints) { + assert(!_isAttached, _attachedErrorMessage); + _blueprints.addAll(blueprints); + } + + /// Adds a single [Blueprint] to this blueprint. + void addBlueprint(Blueprint blueprint) { + assert(!_isAttached, _attachedErrorMessage); + _blueprints.add(blueprint); + } + /// Returns a copy of the components built by this blueprint List get components => List.unmodifiable(_components); + + /// Returns a copy of the children blueprints + List get blueprints => List.unmodifiable(_blueprints); } /// A [Blueprint] that provides additional diff --git a/lib/game/components/baseboard.dart b/lib/game/components/baseboard.dart index 60d0ebe7..d9dc3512 100644 --- a/lib/game/components/baseboard.dart +++ b/lib/game/components/baseboard.dart @@ -5,7 +5,7 @@ import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; /// {@template baseboard} -/// Straight, angled board piece to corral the [Ball] towards the [Flipper]s. +/// Wing-shaped board piece to corral the [Ball] towards the [Flipper]s. /// {@endtemplate} class Baseboard extends BodyComponent with InitialPosition { /// {@macro baseboard} @@ -13,41 +13,68 @@ class Baseboard extends BodyComponent with InitialPosition { required BoardSide side, }) : _side = side; - /// The width of the [Baseboard]. - static const width = 10.0; - - /// The height of the [Baseboard]. - static const height = 2.0; + /// The size of the [Baseboard]. + static final size = Vector2(24.2, 13.5); /// Whether the [Baseboard] is on the left or right side of the board. final BoardSide _side; List _createFixtureDefs() { final fixturesDef = []; + final direction = _side.direction; + final arcsAngle = -1.11 * direction; + const arcsRotation = math.pi / 2.08; + + final topCircleShape = CircleShape()..radius = 0.7; + topCircleShape.position.setValues(11.39 * direction, 6.05); + final topCircleFixtureDef = FixtureDef(topCircleShape); + fixturesDef.add(topCircleFixtureDef); + + final innerEdgeShape = EdgeShape() + ..set( + Vector2(10.86 * direction, 6.45), + Vector2(6.96 * direction, 0.25), + ); + final innerEdgeShapeFixtureDef = FixtureDef(innerEdgeShape); + fixturesDef.add(innerEdgeShapeFixtureDef); + + final outerEdgeShape = EdgeShape() + ..set( + Vector2(11.96 * direction, 5.85), + Vector2(5.48 * direction, -4.85), + ); + final outerEdgeShapeFixtureDef = FixtureDef(outerEdgeShape); + fixturesDef.add(outerEdgeShapeFixtureDef); + + final upperArcFixtureDefs = Pathway.arc( + center: Vector2(1.76 * direction, 3.25), + width: 0, + radius: 6.1, + angle: arcsAngle, + rotation: arcsRotation, + singleWall: true, + ).createFixtureDefs(); + fixturesDef.addAll(upperArcFixtureDefs); + + final lowerArcFixtureDefs = Pathway.arc( + center: Vector2(1.85 * direction, -2.15), + width: 0, + radius: 4.5, + angle: arcsAngle, + rotation: arcsRotation, + singleWall: true, + ).createFixtureDefs(); + fixturesDef.addAll(lowerArcFixtureDefs); - final circleShape1 = CircleShape()..radius = Baseboard.height / 2; - circleShape1.position.setValues( - -(Baseboard.width / 2) + circleShape1.radius, - 0, - ); - final circle1FixtureDef = FixtureDef(circleShape1); - fixturesDef.add(circle1FixtureDef); - - final circleShape2 = CircleShape()..radius = Baseboard.height / 2; - circleShape2.position.setValues( - (Baseboard.width / 2) - circleShape2.radius, - 0, - ); - final circle2FixtureDef = FixtureDef(circleShape2); - fixturesDef.add(circle2FixtureDef); - - final rectangle = PolygonShape() - ..setAsBoxXY( - (Baseboard.width - Baseboard.height) / 2, - Baseboard.height / 2, + final bottomRectangle = PolygonShape() + ..setAsBox( + 7, + 2, + Vector2(-5.14 * direction, -4.75), + 0, ); - final rectangleFixtureDef = FixtureDef(rectangle); - fixturesDef.add(rectangleFixtureDef); + final bottomRectangleFixtureDef = FixtureDef(bottomRectangle); + fixturesDef.add(bottomRectangleFixtureDef); return fixturesDef; } @@ -56,7 +83,7 @@ class Baseboard extends BodyComponent with InitialPosition { Body createBody() { // TODO(allisonryan0002): share sweeping angle with flipper when components // are grouped. - const angle = math.pi / 7; + const angle = math.pi / 5; final bodyDef = BodyDef() ..position = initialPosition diff --git a/lib/game/components/board.dart b/lib/game/components/board.dart index 6e895d6e..c771b9d8 100644 --- a/lib/game/components/board.dart +++ b/lib/game/components/board.dart @@ -1,11 +1,9 @@ import 'package:flame/components.dart'; import 'package:pinball/game/game.dart'; -import 'package:pinball_components/pinball_components.dart'; /// {@template board} -/// The main flat surface of the [PinballGame], where the [Flipper]s, -/// [RoundBumper]s, [Kicker]s are arranged. -/// {entemplate} +/// The main flat surface of the [PinballGame]. +/// {endtemplate} class Board extends Component { /// {@macro board} Board(); @@ -21,7 +19,7 @@ class Board extends Component { spacing: 2, ); - final dashForest = _FlutterForest( + final flutterForest = FlutterForest( position: Vector2( PinballGame.boardBounds.center.dx + 20, PinballGame.boardBounds.center.dy + 48, @@ -30,44 +28,7 @@ class Board extends Component { await addAll([ bottomGroup, - dashForest, - ]); - } -} - -/// {@template flutter_forest} -/// Area positioned at the top right of the [Board] where the [Ball] -/// can bounce off [RoundBumper]s. -/// {@endtemplate} -class _FlutterForest extends Component { - /// {@macro flutter_forest} - _FlutterForest({ - required this.position, - }); - - final Vector2 position; - - @override - Future onLoad() async { - // TODO(alestiago): adjust positioning once sprites are added. - // TODO(alestiago): Use [NestBumper] instead of [RoundBumper] once provided. - final smallLeftNest = RoundBumper( - radius: 1, - points: 10, - )..initialPosition = position + Vector2(-4.8, 2.8); - final smallRightNest = RoundBumper( - radius: 1, - points: 10, - )..initialPosition = position + Vector2(0.5, -5.5); - final bigNest = RoundBumper( - radius: 2, - points: 20, - )..initialPosition = position; - - await addAll([ - smallLeftNest, - smallRightNest, - bigNest, + flutterForest, ]); } } @@ -134,8 +95,8 @@ class _BottomGroupSide extends Component { final baseboard = Baseboard(side: _side) ..initialPosition = _position + Vector2( - (Flipper.size.x * direction) - direction, - Flipper.size.y, + (Baseboard.size.x / 1.6 * direction), + Baseboard.size.y - 2, ); final kicker = Kicker( side: _side, diff --git a/lib/game/components/bonus_word.dart b/lib/game/components/bonus_word.dart index d97a9bd1..9dc9b0b0 100644 --- a/lib/game/components/bonus_word.dart +++ b/lib/game/components/bonus_word.dart @@ -21,13 +21,9 @@ class BonusWord extends Component with BlocComponent { @override bool listenWhen(GameState? previousState, GameState newState) { - if ((previousState?.bonusHistory.length ?? 0) < + return (previousState?.bonusHistory.length ?? 0) < newState.bonusHistory.length && - newState.bonusHistory.last == GameBonus.word) { - return true; - } - - return false; + newState.bonusHistory.last == GameBonus.word; } @override diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 1ed293da..07b036f6 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -4,6 +4,7 @@ export 'board.dart'; export 'board_side.dart'; export 'bonus_word.dart'; export 'flipper.dart'; +export 'flutter_forest.dart'; export 'jetpack_ramp.dart'; export 'joint_anchor.dart'; export 'kicker.dart'; @@ -11,7 +12,6 @@ export 'launcher_ramp.dart'; export 'pathway.dart'; export 'plunger.dart'; export 'ramp_opening.dart'; -export 'round_bumper.dart'; export 'score_points.dart'; export 'spaceship.dart'; export 'wall.dart'; diff --git a/lib/game/components/flutter_forest.dart b/lib/game/components/flutter_forest.dart new file mode 100644 index 00000000..51dcd90a --- /dev/null +++ b/lib/game/components/flutter_forest.dart @@ -0,0 +1,131 @@ +// ignore_for_file: avoid_renaming_method_parameters + +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/flame/blueprint.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart'; + +/// {@template flutter_forest} +/// Area positioned at the top right of the [Board] where the [Ball] +/// can bounce off [DashNestBumper]s. +/// +/// When all [DashNestBumper]s are hit at least once, the [GameBonus.dashNest] +/// is awarded, and the [BigDashNestBumper] releases a new [Ball]. +/// {@endtemplate} +// TODO(alestiago): Make a [Blueprint] once nesting [Blueprint] is implemented. +class FlutterForest extends Component + with HasGameRef, BlocComponent { + /// {@macro flutter_forest} + FlutterForest({ + required this.position, + }); + + /// The position of the [FlutterForest] on the [Board]. + final Vector2 position; + + @override + bool listenWhen(GameState? previousState, GameState newState) { + return (previousState?.bonusHistory.length ?? 0) < + newState.bonusHistory.length && + newState.bonusHistory.last == GameBonus.dashNest; + } + + @override + void onNewState(GameState state) { + super.onNewState(state); + gameRef.addFromBlueprint(BallBlueprint(position: position)); + } + + @override + Future onLoad() async { + gameRef.addContactCallback(DashNestBumperBallContactCallback()); + + // TODO(alestiago): adjust positioning once sprites are added. + final smallLeftNest = SmallDashNestBumper(id: 'small_left_nest') + ..initialPosition = position + Vector2(-4.8, 2.8); + final smallRightNest = SmallDashNestBumper(id: 'small_right_nest') + ..initialPosition = position + Vector2(0.5, -5.5); + final bigNest = BigDashNestBumper(id: 'big_nest') + ..initialPosition = position; + + await addAll([ + smallLeftNest, + smallRightNest, + bigNest, + ]); + } +} + +/// {@template dash_nest_bumper} +/// Bumper located in the [FlutterForest]. +/// {@endtemplate} +@visibleForTesting +abstract class DashNestBumper extends BodyComponent + with ScorePoints, InitialPosition { + /// {@macro dash_nest_bumper} + DashNestBumper({required this.id}); + + /// Unique identifier for this [DashNestBumper]. + /// + /// Used to identify [DashNestBumper]s in [GameState.activatedDashNests]. + final String id; +} + +/// Listens when a [Ball] bounces bounces against a [DashNestBumper]. +@visibleForTesting +class DashNestBumperBallContactCallback + extends ContactCallback { + @override + void begin(DashNestBumper dashNestBumper, Ball ball, Contact _) { + dashNestBumper.gameRef.read().add( + DashNestActivated(dashNestBumper.id), + ); + } +} + +/// {@macro dash_nest_bumper} +@visibleForTesting +class BigDashNestBumper extends DashNestBumper { + /// {@macro dash_nest_bumper} + BigDashNestBumper({required String id}) : super(id: id); + + @override + int get points => 20; + + @override + Body createBody() { + final shape = CircleShape()..radius = 2.5; + final fixtureDef = FixtureDef(shape); + + final bodyDef = BodyDef() + ..position = initialPosition + ..userData = this; + + return world.createBody(bodyDef)..createFixture(fixtureDef); + } +} + +/// {@macro dash_nest_bumper} +@visibleForTesting +class SmallDashNestBumper extends DashNestBumper { + /// {@macro dash_nest_bumper} + SmallDashNestBumper({required String id}) : super(id: id); + + @override + int get points => 10; + + @override + Body createBody() { + final shape = CircleShape()..radius = 1; + final fixtureDef = FixtureDef(shape); + + final bodyDef = BodyDef() + ..position = initialPosition + ..userData = this; + + return world.createBody(bodyDef)..createFixture(fixtureDef); + } +} diff --git a/lib/game/components/round_bumper.dart b/lib/game/components/round_bumper.dart deleted file mode 100644 index 969bddbe..00000000 --- a/lib/game/components/round_bumper.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:flame_forge2d/flame_forge2d.dart'; -import 'package:pinball/game/game.dart'; -import 'package:pinball_components/pinball_components.dart'; - -/// {@template round_bumper} -/// Circular body that repels a [Ball] on contact, increasing the score. -/// {@endtemplate} -class RoundBumper extends BodyComponent with ScorePoints, InitialPosition { - /// {@macro round_bumper} - RoundBumper({ - required double radius, - required int points, - }) : _radius = radius, - _points = points; - - /// The radius of the [RoundBumper]. - final double _radius; - - /// Points awarded from hitting this [RoundBumper]. - final int _points; - - @override - int get points => _points; - - @override - Body createBody() { - final shape = CircleShape()..radius = _radius; - - final fixtureDef = FixtureDef(shape)..restitution = 1; - - final bodyDef = BodyDef()..position = initialPosition; - - return world.createBody(bodyDef)..createFixture(fixtureDef); - } -} diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index ba75412b..6e81fe77 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -17,8 +17,6 @@ class $AssetsImagesComponentsGen { AssetGenImage get flipper => const AssetGenImage('assets/images/components/flipper.png'); - AssetGenImage get sauce => - const AssetGenImage('assets/images/components/sauce.png'); $AssetsImagesComponentsSpaceshipGen get spaceship => const $AssetsImagesComponentsSpaceshipGen(); } diff --git a/test/flame/blueprint_test.dart b/test/flame/blueprint_test.dart index 3a9f5ed3..e5fc2c4f 100644 --- a/test/flame/blueprint_test.dart +++ b/test/flame/blueprint_test.dart @@ -14,6 +14,28 @@ class MyBlueprint extends Blueprint { } } +class MyOtherBlueprint extends Blueprint { + @override + void build(_) { + add(Component()); + } +} + +class YetMyOtherBlueprint extends Blueprint { + @override + void build(_) { + add(Component()); + } +} + +class MyComposedBlueprint extends Blueprint { + @override + void build(_) { + addBlueprint(MyBlueprint()); + addAllBlueprints([MyOtherBlueprint(), YetMyOtherBlueprint()]); + } +} + class MyForge2dBlueprint extends Forge2DBlueprint { @override void build(_) { @@ -24,12 +46,23 @@ class MyForge2dBlueprint extends Forge2DBlueprint { void main() { group('Blueprint', () { + setUpAll(() { + registerFallbackValue(MyBlueprint()); + registerFallbackValue(Component()); + }); + test('components can be added to it', () { final blueprint = MyBlueprint()..build(MockPinballGame()); expect(blueprint.components.length, equals(3)); }); + test('blueprints can be added to it', () { + final blueprint = MyComposedBlueprint()..build(MockPinballGame()); + + expect(blueprint.blueprints.length, equals(3)); + }); + test('adds the components to a game on attach', () { final mockGame = MockPinballGame(); when(() => mockGame.addAll(any())).thenAnswer((_) async {}); @@ -38,6 +71,14 @@ void main() { verify(() => mockGame.addAll(any())).called(1); }); + test('adds components from a child Blueprint the to a game on attach', () { + final mockGame = MockPinballGame(); + when(() => mockGame.addAll(any())).thenAnswer((_) async {}); + MyComposedBlueprint().attach(mockGame); + + verify(() => mockGame.addAll(any())).called(4); + }); + test( 'throws assertion error when adding to an already attached blueprint', () async { diff --git a/test/game/components/baseboard_test.dart b/test/game/components/baseboard_test.dart index 75cc62cc..f834a41e 100644 --- a/test/game/components/baseboard_test.dart +++ b/test/game/components/baseboard_test.dart @@ -61,14 +61,14 @@ void main() { group('fixtures', () { flameTester.test( - 'has three', + 'has six', (game) async { final baseboard = Baseboard( side: BoardSide.left, ); await game.ensureAdd(baseboard); - expect(baseboard.body.fixtures.length, equals(3)); + expect(baseboard.body.fixtures.length, equals(6)); }, ); }); diff --git a/test/game/components/board_test.dart b/test/game/components/board_test.dart index f0cd0e16..5a4b95dc 100644 --- a/test/game/components/board_test.dart +++ b/test/game/components/board_test.dart @@ -75,15 +75,15 @@ void main() { ); flameTester.test( - 'has three RoundBumpers', + 'has one FlutterForest', (game) async { // TODO(alestiago): change to [NestBumpers] once provided. final board = Board(); await game.ready(); await game.ensureAdd(board); - final roundBumpers = board.descendants().whereType(); - expect(roundBumpers.length, equals(3)); + final flutterForest = board.descendants().whereType(); + expect(flutterForest.length, equals(1)); }, ); }); diff --git a/test/game/components/bonus_word_test.dart b/test/game/components/bonus_word_test.dart index a12a5a74..afd69935 100644 --- a/test/game/components/bonus_word_test.dart +++ b/test/game/components/bonus_word_test.dart @@ -194,6 +194,7 @@ void main() { group('bonus letter activation', () { final gameBloc = MockGameBloc(); + final tester = flameBlocTester(gameBloc: () => gameBloc); BonusLetter _getBonusLetter(PinballGame game) { return game.children @@ -212,8 +213,6 @@ void main() { ); }); - final tester = flameBlocTester(gameBloc: () => gameBloc); - tester.widgetTest( 'adds BonusLetterActivated to GameBloc when not activated', (game, tester) async { diff --git a/test/game/components/flutter_forest_test.dart b/test/game/components/flutter_forest_test.dart new file mode 100644 index 00000000..f960796c --- /dev/null +++ b/test/game/components/flutter_forest_test.dart @@ -0,0 +1,125 @@ +// ignore_for_file: cascade_invocations + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_forge2d/flame_forge2d.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'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(PinballGameTest.create); + + group('FlutterForest', () { + flameTester.test( + 'loads correctly', + (game) async { + await game.ready(); + final flutterForest = FlutterForest(position: Vector2(0, 0)); + await game.ensureAdd(flutterForest); + + expect(game.contains(flutterForest), isTrue); + }, + ); + + flameTester.test( + 'onNewState adds a new ball', + (game) async { + final flutterForest = FlutterForest(position: Vector2(0, 0)); + await game.ready(); + await game.ensureAdd(flutterForest); + + final previousBalls = game.descendants().whereType().length; + flutterForest.onNewState(MockGameState()); + await game.ready(); + + expect( + game.descendants().whereType().length, + greaterThan(previousBalls), + ); + }, + ); + + group('listenWhen', () { + final gameBloc = MockGameBloc(); + final tester = flameBlocTester(gameBloc: () => gameBloc); + + setUp(() { + whenListen( + gameBloc, + const Stream.empty(), + initialState: const GameState.initial(), + ); + }); + + tester.widgetTest( + 'listens when a Bonus.dashNest is added', + (game, tester) async { + await game.ready(); + final flutterForest = + game.descendants().whereType().first; + + const state = GameState( + score: 0, + balls: 3, + activatedBonusLetters: [], + activatedDashNests: {}, + bonusHistory: [GameBonus.dashNest], + ); + + expect( + flutterForest.listenWhen(const GameState.initial(), state), + isTrue, + ); + }, + ); + }); + }); + + group('DashNestBumperBallContactCallback', () { + final gameBloc = MockGameBloc(); + final tester = flameBlocTester(gameBloc: () => gameBloc); + + setUp(() { + whenListen( + gameBloc, + const Stream.empty(), + initialState: const GameState.initial(), + ); + }); + + tester.widgetTest( + 'adds a DashNestActivated event with DashNestBumper.id', + (game, tester) async { + final contactCallback = DashNestBumperBallContactCallback(); + const id = '0'; + final dashNestBumper = MockDashNestBumper(); + when(() => dashNestBumper.id).thenReturn(id); + when(() => dashNestBumper.gameRef).thenReturn(game); + + contactCallback.begin(dashNestBumper, MockBall(), MockContact()); + + verify(() => gameBloc.add(DashNestActivated(dashNestBumper.id))) + .called(1); + }, + ); + }); + + group('BigDashNestBumper', () { + test('has points', () { + final dashNestBumper = BigDashNestBumper(id: ''); + expect(dashNestBumper.points, greaterThan(0)); + }); + }); + + group('SmallDashNestBumper', () { + test('has points', () { + final dashNestBumper = SmallDashNestBumper(id: ''); + expect(dashNestBumper.points, greaterThan(0)); + }); + }); +} diff --git a/test/game/components/round_bumper_test.dart b/test/game/components/round_bumper_test.dart deleted file mode 100644 index 437167ad..00000000 --- a/test/game/components/round_bumper_test.dart +++ /dev/null @@ -1,102 +0,0 @@ -// ignore_for_file: cascade_invocations - -import 'package:flame_forge2d/flame_forge2d.dart'; -import 'package:flame_test/flame_test.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:pinball/game/game.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - group('RoundBumper', () { - final flameTester = FlameTester(Forge2DGame.new); - const radius = 1.0; - const points = 1; - - flameTester.test( - 'loads correctly', - (game) async { - await game.ready(); - final roundBumper = RoundBumper( - radius: radius, - points: points, - ); - await game.ensureAdd(roundBumper); - - expect(game.contains(roundBumper), isTrue); - }, - ); - - flameTester.test( - 'has points', - (game) async { - final roundBumper = RoundBumper( - radius: radius, - points: points, - ); - await game.ensureAdd(roundBumper); - - expect(roundBumper.points, equals(points)); - }, - ); - - group('body', () { - flameTester.test( - 'is static', - (game) async { - final roundBumper = RoundBumper( - radius: radius, - points: points, - ); - await game.ensureAdd(roundBumper); - - expect(roundBumper.body.bodyType, equals(BodyType.static)); - }, - ); - }); - - group('fixture', () { - flameTester.test( - 'exists', - (game) async { - final roundBumper = RoundBumper( - radius: radius, - points: points, - ); - await game.ensureAdd(roundBumper); - - expect(roundBumper.body.fixtures[0], isA()); - }, - ); - - flameTester.test( - 'has restitution', - (game) async { - final roundBumper = RoundBumper( - radius: radius, - points: points, - ); - await game.ensureAdd(roundBumper); - - final fixture = roundBumper.body.fixtures[0]; - expect(fixture.restitution, greaterThan(0)); - }, - ); - - flameTester.test( - 'shape is circular', - (game) async { - final roundBumper = RoundBumper( - radius: radius, - points: points, - ); - await game.ensureAdd(roundBumper); - - final fixture = roundBumper.body.fixtures[0]; - expect(fixture.shape.shapeType, equals(ShapeType.circle)); - expect(fixture.shape.radius, equals(1)); - }, - ); - }); - }); -} diff --git a/test/helpers/mocks.dart b/test/helpers/mocks.dart index 99dd8312..c658c531 100644 --- a/test/helpers/mocks.dart +++ b/test/helpers/mocks.dart @@ -73,3 +73,5 @@ class MockSpaceshipEntrance extends Mock implements SpaceshipEntrance {} class MockSpaceshipHole extends Mock implements SpaceshipHole {} class MockComponentSet extends Mock implements ComponentSet {} + +class MockDashNestBumper extends Mock implements DashNestBumper {}