From 6b67525716fe398182134ccab457d2ed9c57bdc0 Mon Sep 17 00:00:00 2001 From: Alejandro Santiago Date: Sat, 7 May 2022 16:39:55 +0100 Subject: [PATCH] fix: flying ball when entering SpaceshipRamp (#380) --- .../lib/src/components/components.dart | 1 - .../components/layer_sensor/layer_sensor.dart | 1 + .../spaceship_ramp/spaceship_ramp.dart | 128 ++++++++++++++---- .../android_acres/android_spaceship_game.dart | 1 + .../android_acres/spaceship_rail_game.dart | 1 + .../android_acres/spaceship_ramp_game.dart | 4 + .../lib/stories/ball/basic_ball_game.dart | 1 + .../stories/launch_ramp/launch_ramp_game.dart | 1 + .../sandbox/lib/stories/layer/layer_game.dart | 1 + .../test/src/components/ball/ball_test.dart | 1 + .../layer_filtering_behavior_test.dart | 1 + .../layer_sensor/layer_sensor_test.dart | 1 + packages/pinball_flame/lib/pinball_flame.dart | 3 +- .../lib/src/behaviors/behaviors.dart | 3 + .../src/{ => behaviors}/contact_behavior.dart | 0 .../src/behaviors/layer_contact_behavior.dart | 20 +++ .../behaviors/z_index_contact_behavior.dart | 20 +++ .../lib/src}/layer.dart | 0 .../test}/layer_test.dart | 35 ++--- .../contact_behavior_test.dart | 0 .../layer_contact_behavior_test.dart | 60 ++++++++ .../z_index_contact_behavior_test.dart | 60 ++++++++ 22 files changed, 300 insertions(+), 43 deletions(-) create mode 100644 packages/pinball_flame/lib/src/behaviors/behaviors.dart rename packages/pinball_flame/lib/src/{ => behaviors}/contact_behavior.dart (100%) create mode 100644 packages/pinball_flame/lib/src/behaviors/layer_contact_behavior.dart create mode 100644 packages/pinball_flame/lib/src/behaviors/z_index_contact_behavior.dart rename packages/{pinball_components/lib/src/components => pinball_flame/lib/src}/layer.dart (100%) rename packages/{pinball_components/test/src/components => pinball_flame/test}/layer_test.dart (82%) rename packages/pinball_flame/test/src/{ => behaviors}/contact_behavior_test.dart (100%) create mode 100644 packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart create mode 100644 packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart diff --git a/packages/pinball_components/lib/src/components/components.dart b/packages/pinball_components/lib/src/components/components.dart index 54345772..7fda6272 100644 --- a/packages/pinball_components/lib/src/components/components.dart +++ b/packages/pinball_components/lib/src/components/components.dart @@ -21,7 +21,6 @@ export 'initial_position.dart'; export 'joint_anchor.dart'; export 'kicker/kicker.dart'; export 'launch_ramp.dart'; -export 'layer.dart'; export 'layer_sensor/layer_sensor.dart'; export 'multiball/multiball.dart'; export 'multiplier/multiplier.dart'; diff --git a/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart b/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart index 6e0807f6..dc43322c 100644 --- a/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart +++ b/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart @@ -1,6 +1,7 @@ import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/src/components/layer_sensor/behaviors/layer_filtering_behavior.dart'; +import 'package:pinball_flame/pinball_flame.dart'; /// {@template layer_entrance_orientation} /// Determines if a layer entrance is oriented [up] or [down] on the board. diff --git a/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart b/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart index 02095652..0796be92 100644 --- a/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart +++ b/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart @@ -32,12 +32,6 @@ class SpaceshipRamp extends Component { RampBallAscendingContactBehavior(), ], )..initialPosition = Vector2(1.7, -20.4), - _SpaceshipRampOpening( - outsidePriority: ZIndexes.ballOnBoard, - rotation: math.pi, - ) - ..initialPosition = Vector2(1.7, -19.8) - ..layer = Layer.opening, _SpaceshipRampOpening( outsideLayer: Layer.spaceship, outsidePriority: ZIndexes.ballOnSpaceship, @@ -46,10 +40,9 @@ class SpaceshipRamp extends Component { ..initialPosition = Vector2(-13.7, -18.6) ..layer = Layer.spaceshipEntranceRamp, _SpaceshipRampBackground(), - _SpaceshipRampBoardOpeningSpriteComponent() - ..position = Vector2(3.4, -39.5), + _SpaceshipRampBoardOpening()..initialPosition = Vector2(3.4, -39.5), _SpaceshipRampForegroundRailing(), - _SpaceshipRampBase()..initialPosition = Vector2(1.7, -20), + _SpaceshipRampBase()..initialPosition = Vector2(3.4, -42.5), _SpaceshipRampBackgroundRailingSpriteComponent(), SpaceshipRampArrowSpriteComponent( current: bloc.state.hits, @@ -253,12 +246,103 @@ extension on SpaceshipRampArrowSpriteState { } } -class _SpaceshipRampBoardOpeningSpriteComponent extends SpriteComponent - with HasGameRef, ZIndex { - _SpaceshipRampBoardOpeningSpriteComponent() : super(anchor: Anchor.center) { +class _SpaceshipRampBoardOpening extends BodyComponent + with Layered, ZIndex, InitialPosition { + _SpaceshipRampBoardOpening() + : super( + renderBody: false, + children: [ + _SpaceshipRampBoardOpeningSpriteComponent(), + LayerContactBehavior(layer: Layer.spaceshipEntranceRamp) + ..applyTo(['inside']), + LayerContactBehavior(layer: Layer.board)..applyTo(['outside']), + ZIndexContactBehavior(zIndex: ZIndexes.ballOnBoard) + ..applyTo(['outside']), + ZIndexContactBehavior(zIndex: ZIndexes.ballOnSpaceshipRamp) + ..applyTo(['middle', 'inside']), + ], + ) { zIndex = ZIndexes.spaceshipRampBoardOpening; + layer = Layer.opening; } + List _createFixtureDefs() { + final topEdge = EdgeShape() + ..set( + Vector2(-3.4, -1.2), + Vector2(3.4, -1.6), + ); + final bottomEdge = EdgeShape() + ..set( + Vector2(-6.2, 1.5), + Vector2(6.2, 1.5), + ); + final middleCurve = BezierCurveShape( + controlPoints: [ + topEdge.vertex1, + Vector2(0, 2.3), + Vector2(7.5, 2.3), + topEdge.vertex2, + ], + ); + final leftCurve = BezierCurveShape( + controlPoints: [ + Vector2(-4.4, -1.2), + Vector2(-4.65, 0), + bottomEdge.vertex1, + ], + ); + final rightCurve = BezierCurveShape( + controlPoints: [ + Vector2(4.4, -1.6), + Vector2(4.65, 0), + bottomEdge.vertex2, + ], + ); + + const outsideKey = 'outside'; + return [ + FixtureDef( + topEdge, + isSensor: true, + userData: 'inside', + ), + FixtureDef( + bottomEdge, + isSensor: true, + userData: outsideKey, + ), + FixtureDef( + middleCurve, + isSensor: true, + userData: 'middle', + ), + FixtureDef( + leftCurve, + isSensor: true, + userData: outsideKey, + ), + FixtureDef( + rightCurve, + isSensor: true, + userData: outsideKey, + ), + ]; + } + + @override + Body createBody() { + final bodyDef = BodyDef(position: initialPosition); + final body = world.createBody(bodyDef); + _createFixtureDefs().forEach(body.createFixture); + return body; + } +} + +class _SpaceshipRampBoardOpeningSpriteComponent extends SpriteComponent + with HasGameRef { + _SpaceshipRampBoardOpeningSpriteComponent() : super(anchor: Anchor.center); + @override Future onLoad() async { await super.onLoad(); @@ -342,28 +426,23 @@ class _SpaceshipRampForegroundRailingSpriteComponent extends SpriteComponent } } -class _SpaceshipRampBase extends BodyComponent with InitialPosition, Layered { +class _SpaceshipRampBase extends BodyComponent with Layered, InitialPosition { _SpaceshipRampBase() : super(renderBody: false) { layer = Layer.board; } @override Body createBody() { - const baseWidth = 9; - final baseShape = BezierCurveShape( + final shape = BezierCurveShape( controlPoints: [ - Vector2(initialPosition.x - baseWidth / 2, initialPosition.y), - Vector2(initialPosition.x - baseWidth / 2, initialPosition.y) + - Vector2(2, -5), - Vector2(initialPosition.x + baseWidth / 2, initialPosition.y) + - Vector2(-2, -5), - Vector2(initialPosition.x + baseWidth / 2, initialPosition.y) + Vector2(-4.25, 1.75), + Vector2(-2, -2.1), + Vector2(2, -2.3), + Vector2(4.1, 1.5), ], ); - final fixtureDef = FixtureDef(baseShape); final bodyDef = BodyDef(position: initialPosition); - - return world.createBody(bodyDef)..createFixture(fixtureDef); + return world.createBody(bodyDef)..createFixtureFromShape(shape); } } @@ -419,7 +498,6 @@ class RampScoringSensor extends BodyComponent } /// Creates a [RampScoringSensor] without any children. - /// @visibleForTesting RampScoringSensor.test(); diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart index 976f4894..185f5351 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flame/input.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 AndroidSpaceshipGame extends BallGame { diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart index 4093ad33..9acee409 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flame/input.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 SpaceshipRailGame extends BallGame { diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart index fe4e6dae..1027002a 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart @@ -4,6 +4,7 @@ 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 BallGame with KeyboardEvents { @@ -33,6 +34,9 @@ class SpaceshipRampGame extends BallGame with KeyboardEvents { - Press space to progress arrow sprites. '''; + @override + Color backgroundColor() => Colors.white; + late final SpaceshipRamp _spaceshipRamp; @override 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 f3ba50f3..b5e29a8e 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 @@ -1,5 +1,6 @@ import 'package:flame/input.dart'; import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_theme/pinball_theme.dart' as theme; import 'package:sandbox/common/common.dart'; 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 index b6955a26..c1d435d5 100644 --- 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 @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flame/input.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 LaunchRampGame extends BallGame { diff --git a/packages/pinball_components/sandbox/lib/stories/layer/layer_game.dart b/packages/pinball_components/sandbox/lib/stories/layer/layer_game.dart index 40dcc824..808a43eb 100644 --- a/packages/pinball_components/sandbox/lib/stories/layer/layer_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/layer/layer_game.dart @@ -2,6 +2,7 @@ import 'package:flame/input.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/material.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 LayerGame extends BallGame with TapDetector { diff --git a/packages/pinball_components/test/src/components/ball/ball_test.dart b/packages/pinball_components/test/src/components/ball/ball_test.dart index 43454342..9bf0bf27 100644 --- a/packages/pinball_components/test/src/components/ball/ball_test.dart +++ b/packages/pinball_components/test/src/components/ball/ball_test.dart @@ -5,6 +5,7 @@ import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_theme/pinball_theme.dart' as theme; import '../../../helpers/helpers.dart'; diff --git a/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart b/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart index b7bc308b..b8701656 100644 --- a/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart +++ b/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart @@ -6,6 +6,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/src/components/layer_sensor/behaviors/behaviors.dart'; +import 'package:pinball_flame/pinball_flame.dart'; import '../../../../helpers/helpers.dart'; diff --git a/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart b/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart index dd32ad56..2966b106 100644 --- a/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart +++ b/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart @@ -4,6 +4,7 @@ import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/src/components/layer_sensor/behaviors/behaviors.dart'; +import 'package:pinball_flame/pinball_flame.dart'; import '../../../helpers/helpers.dart'; diff --git a/packages/pinball_flame/lib/pinball_flame.dart b/packages/pinball_flame/lib/pinball_flame.dart index 38f09b59..bc3cae0e 100644 --- a/packages/pinball_flame/lib/pinball_flame.dart +++ b/packages/pinball_flame/lib/pinball_flame.dart @@ -1,10 +1,11 @@ library pinball_flame; +export 'src/behaviors/behaviors.dart'; export 'src/canvas/canvas.dart'; export 'src/component_controller.dart'; -export 'src/contact_behavior.dart'; export 'src/flame_provider.dart'; export 'src/keyboard_input_controller.dart'; +export 'src/layer.dart'; export 'src/parent_is_a.dart'; export 'src/pinball_forge2d_game.dart'; export 'src/sprite_animation.dart'; diff --git a/packages/pinball_flame/lib/src/behaviors/behaviors.dart b/packages/pinball_flame/lib/src/behaviors/behaviors.dart new file mode 100644 index 00000000..fa80c97f --- /dev/null +++ b/packages/pinball_flame/lib/src/behaviors/behaviors.dart @@ -0,0 +1,3 @@ +export 'contact_behavior.dart'; +export 'layer_contact_behavior.dart'; +export 'z_index_contact_behavior.dart'; diff --git a/packages/pinball_flame/lib/src/contact_behavior.dart b/packages/pinball_flame/lib/src/behaviors/contact_behavior.dart similarity index 100% rename from packages/pinball_flame/lib/src/contact_behavior.dart rename to packages/pinball_flame/lib/src/behaviors/contact_behavior.dart diff --git a/packages/pinball_flame/lib/src/behaviors/layer_contact_behavior.dart b/packages/pinball_flame/lib/src/behaviors/layer_contact_behavior.dart new file mode 100644 index 00000000..a73b94a5 --- /dev/null +++ b/packages/pinball_flame/lib/src/behaviors/layer_contact_behavior.dart @@ -0,0 +1,20 @@ +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +/// {@template layer_contact_behavior} +/// Switches the [Layer] of any [Layered] body that contacts with it. +/// {@endtemplate} +class LayerContactBehavior extends ContactBehavior { + /// {@macro layer_contact_behavior} + LayerContactBehavior({required Layer layer}) : _layer = layer; + + final Layer _layer; + + @override + void beginContact(Object other, Contact contact) { + super.beginContact(other, contact); + if (other is! Layered) return; + if (other.layer == _layer) return; + other.layer = _layer; + } +} diff --git a/packages/pinball_flame/lib/src/behaviors/z_index_contact_behavior.dart b/packages/pinball_flame/lib/src/behaviors/z_index_contact_behavior.dart new file mode 100644 index 00000000..ea9bfcad --- /dev/null +++ b/packages/pinball_flame/lib/src/behaviors/z_index_contact_behavior.dart @@ -0,0 +1,20 @@ +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +/// {@template layer_contact_behavior} +/// Switches the z-index of any [ZIndex] body that contacts with it. +/// {@endtemplate} +class ZIndexContactBehavior extends ContactBehavior { + /// {@macro layer_contact_behavior} + ZIndexContactBehavior({required int zIndex}) : _zIndex = zIndex; + + final int _zIndex; + + @override + void beginContact(Object other, Contact contact) { + super.beginContact(other, contact); + if (other is! ZIndex) return; + if (other.zIndex == _zIndex) return; + other.zIndex = _zIndex; + } +} diff --git a/packages/pinball_components/lib/src/components/layer.dart b/packages/pinball_flame/lib/src/layer.dart similarity index 100% rename from packages/pinball_components/lib/src/components/layer.dart rename to packages/pinball_flame/lib/src/layer.dart diff --git a/packages/pinball_components/test/src/components/layer_test.dart b/packages/pinball_flame/test/layer_test.dart similarity index 82% rename from packages/pinball_components/test/src/components/layer_test.dart rename to packages/pinball_flame/test/layer_test.dart index d47702ea..93ab29a6 100644 --- a/packages/pinball_components/test/src/components/layer_test.dart +++ b/packages/pinball_flame/test/layer_test.dart @@ -4,9 +4,9 @@ import 'dart:math' as math; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; -class TestLayeredBodyComponent extends BodyComponent with Layered { +class _TestLayeredBodyComponent extends BodyComponent with Layered { @override Body createBody() { final fixtureDef = FixtureDef(CircleShape()); @@ -14,7 +14,7 @@ class TestLayeredBodyComponent extends BodyComponent with Layered { } } -class TestBodyComponent extends BodyComponent { +class _TestBodyComponent extends BodyComponent { @override Body createBody() { final fixtureDef = FixtureDef(CircleShape()); @@ -41,12 +41,12 @@ void main() { } flameTester.test('TestBodyComponent has fixtures', (game) async { - final component = TestBodyComponent(); + final component = _TestBodyComponent(); await game.ensureAdd(component); }); test('correctly sets and gets', () { - final component = TestLayeredBodyComponent() + final component = _TestLayeredBodyComponent() ..layer = Layer.spaceshipEntranceRamp; expect(component.layer, Layer.spaceshipEntranceRamp); }); @@ -55,7 +55,7 @@ void main() { 'layers correctly before being loaded', (game) async { const expectedLayer = Layer.spaceshipEntranceRamp; - final component = TestLayeredBodyComponent()..layer = expectedLayer; + final component = _TestLayeredBodyComponent()..layer = expectedLayer; await game.ensureAdd(component); _expectLayerOnFixtures( @@ -70,7 +70,7 @@ void main() { 'when multiple different sets', (game) async { const expectedLayer = Layer.launcher; - final component = TestLayeredBodyComponent() + final component = _TestLayeredBodyComponent() ..layer = Layer.spaceshipEntranceRamp; expect(component.layer, isNot(equals(expectedLayer))); @@ -89,7 +89,7 @@ void main() { 'layers correctly after being loaded', (game) async { const expectedLayer = Layer.spaceshipEntranceRamp; - final component = TestLayeredBodyComponent(); + final component = _TestLayeredBodyComponent(); await game.ensureAdd(component); component.layer = expectedLayer; _expectLayerOnFixtures( @@ -104,7 +104,7 @@ void main() { 'when multiple different sets', (game) async { const expectedLayer = Layer.launcher; - final component = TestLayeredBodyComponent(); + final component = _TestLayeredBodyComponent(); await game.ensureAdd(component); component.layer = Layer.spaceshipEntranceRamp; @@ -122,7 +122,7 @@ void main() { 'defaults to Layer.all ' 'when no layer is given', (game) async { - final component = TestLayeredBodyComponent(); + final component = _TestLayeredBodyComponent(); await game.ensureAdd(component); expect(component.layer, equals(Layer.all)); }, @@ -134,15 +134,18 @@ void main() { const parentLayer = Layer.spaceshipEntranceRamp; const childLayer = Layer.board; - final component = TestLayeredBodyComponent()..layer = parentLayer; - final childComponent = TestLayeredBodyComponent()..layer = childLayer; + final component = _TestLayeredBodyComponent()..layer = parentLayer; + final childComponent = _TestLayeredBodyComponent()..layer = childLayer; await component.add(childComponent); await game.ensureAdd(component); expect(childLayer, isNot(equals(parentLayer))); for (final child in component.children) { - expect((child as TestLayeredBodyComponent).layer, equals(childLayer)); + expect( + (child as _TestLayeredBodyComponent).layer, + equals(childLayer), + ); } }, ); @@ -152,15 +155,15 @@ void main() { (game) async { const parentLayer = Layer.spaceshipEntranceRamp; - final component = TestLayeredBodyComponent()..layer = parentLayer; - final childComponent = TestBodyComponent(); + final component = _TestLayeredBodyComponent()..layer = parentLayer; + final childComponent = _TestBodyComponent(); await component.add(childComponent); await game.ensureAdd(component); for (final child in component.children) { expect( - (child as TestBodyComponent) + (child as _TestBodyComponent) .body .fixtures .first diff --git a/packages/pinball_flame/test/src/contact_behavior_test.dart b/packages/pinball_flame/test/src/behaviors/contact_behavior_test.dart similarity index 100% rename from packages/pinball_flame/test/src/contact_behavior_test.dart rename to packages/pinball_flame/test/src/behaviors/contact_behavior_test.dart diff --git a/packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart b/packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart new file mode 100644 index 00000000..49040977 --- /dev/null +++ b/packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart @@ -0,0 +1,60 @@ +// 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:mocktail/mocktail.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +class _TestBodyComponent extends BodyComponent { + @override + Body createBody() { + final shape = CircleShape()..radius = 1; + return world.createBody(BodyDef())..createFixtureFromShape(shape); + } +} + +class _TestLayeredBodyComponent extends _TestBodyComponent with Layered { + _TestLayeredBodyComponent({required Layer layer}) { + layer = layer; + } +} + +class _MockContact extends Mock implements Contact {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(Forge2DGame.new); + + group('LayerContactBehavior', () { + test('can be instantiated', () { + expect( + LayerContactBehavior(layer: Layer.all), + isA(), + ); + }); + + flameTester.test('can be loaded', (game) async { + final behavior = LayerContactBehavior(layer: Layer.all); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + expect(parent.children, contains(behavior)); + }); + + flameTester.test('beginContact changes layer', (game) async { + const oldLayer = Layer.all; + const newLayer = Layer.board; + final behavior = LayerContactBehavior(layer: newLayer); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + + final component = _TestLayeredBodyComponent(layer: oldLayer); + + behavior.beginContact(component, _MockContact()); + + expect(component.layer, newLayer); + }); + }); +} diff --git a/packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart b/packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart new file mode 100644 index 00000000..ad09004c --- /dev/null +++ b/packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart @@ -0,0 +1,60 @@ +// 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:mocktail/mocktail.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +class _TestBodyComponent extends BodyComponent { + @override + Body createBody() { + final shape = CircleShape()..radius = 1; + return world.createBody(BodyDef())..createFixtureFromShape(shape); + } +} + +class _TestZIndexBodyComponent extends _TestBodyComponent with ZIndex { + _TestZIndexBodyComponent({required int zIndex}) { + zIndex = zIndex; + } +} + +class _MockContact extends Mock implements Contact {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(Forge2DGame.new); + + group('ZIndexContactBehavior', () { + test('can be instantiated', () { + expect( + ZIndexContactBehavior(zIndex: 0), + isA(), + ); + }); + + flameTester.test('can be loaded', (game) async { + final behavior = ZIndexContactBehavior(zIndex: 0); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + expect(parent.children, contains(behavior)); + }); + + flameTester.test('beginContact changes zIndex', (game) async { + const oldIndex = 0; + const newIndex = 1; + final behavior = ZIndexContactBehavior(zIndex: newIndex); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + + final component = _TestZIndexBodyComponent(zIndex: oldIndex); + + behavior.beginContact(component, _MockContact()); + + expect(component.zIndex, newIndex); + }); + }); +}