Merge branch 'main' into feat/add-dino-wall

pull/115/head
RuiAlonso 4 years ago
commit f0fb65ce8d

@ -10,4 +10,5 @@ export 'kicker.dart';
export 'launcher_ramp.dart';
export 'plunger.dart';
export 'score_points.dart';
export 'spaceship_exit_rail.dart';
export 'wall.dart';

@ -114,7 +114,7 @@ class _JetpackRampOpening extends RampOpening {
final double _rotation;
static final Vector2 _size = Vector2(JetpackRamp.width / 3, .1);
static final Vector2 _size = Vector2(JetpackRamp.width / 4, .1);
@override
Shape get shape => PolygonShape()

@ -85,7 +85,7 @@ class Plunger extends BodyComponent with KeyboardHandler, InitialPosition {
plunger: this,
anchor: anchor,
);
world.createJoint(jointDef);
world.createJoint(PrismaticJoint(jointDef));
}
@override

@ -0,0 +1,198 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'dart:math' as math;
import 'dart:ui';
import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets;
/// {@template spaceship_exit_rail}
/// A [Blueprint] for the spaceship drop tube.
/// {@endtemplate}
class SpaceshipExitRail extends Forge2DBlueprint {
/// {@macro spaceship_exit_rail}
SpaceshipExitRail({required this.position});
/// The [position] where the elements will be created
final Vector2 position;
@override
void build(_) {
addAllContactCallback([
SpaceshipExitRailEndBallContactCallback(),
]);
final spaceshipExitRailRamp = _SpaceshipExitRailRamp()
..initialPosition = position;
final exitRail = SpaceshipExitRailEnd()
..initialPosition = position + _SpaceshipExitRailRamp.exitPoint;
addAll([
spaceshipExitRailRamp,
exitRail,
]);
}
}
class _SpaceshipExitRailRamp extends BodyComponent
with InitialPosition, Layered {
_SpaceshipExitRailRamp() : super(priority: 2) {
layer = Layer.spaceshipExitRail;
// TODO(ruimiguel): remove color once asset is placed.
paint = Paint()
..color = const Color.fromARGB(255, 249, 65, 3)
..style = PaintingStyle.stroke;
}
static final exitPoint = Vector2(9.2, -48.5);
List<FixtureDef> _createFixtureDefs() {
const entranceRotationAngle = 175 * math.pi / 180;
const curveRotationAngle = 275 * math.pi / 180;
const exitRotationAngle = 340 * math.pi / 180;
const width = 5.5;
final fixturesDefs = <FixtureDef>[];
final entranceWall = ArcShape(
center: Vector2(width / 2, 0),
arcRadius: width / 2,
angle: math.pi,
rotation: entranceRotationAngle,
);
final entranceFixtureDef = FixtureDef(entranceWall);
fixturesDefs.add(entranceFixtureDef);
final topLeftControlPoints = [
Vector2(0, 0),
Vector2(10, .5),
Vector2(7, 4),
Vector2(15.5, 8.3),
];
final topLeftCurveShape = BezierCurveShape(
controlPoints: topLeftControlPoints,
)..rotate(curveRotationAngle);
final topLeftFixtureDef = FixtureDef(topLeftCurveShape);
fixturesDefs.add(topLeftFixtureDef);
final topRightControlPoints = [
Vector2(0, width),
Vector2(10, 6.5),
Vector2(7, 10),
Vector2(15.5, 13.2),
];
final topRightCurveShape = BezierCurveShape(
controlPoints: topRightControlPoints,
)..rotate(curveRotationAngle);
final topRightFixtureDef = FixtureDef(topRightCurveShape);
fixturesDefs.add(topRightFixtureDef);
final mediumLeftControlPoints = [
topLeftControlPoints.last,
Vector2(21, 12.9),
Vector2(30, 7.1),
Vector2(32, 4.8),
];
final mediumLeftCurveShape = BezierCurveShape(
controlPoints: mediumLeftControlPoints,
)..rotate(curveRotationAngle);
final mediumLeftFixtureDef = FixtureDef(mediumLeftCurveShape);
fixturesDefs.add(mediumLeftFixtureDef);
final mediumRightControlPoints = [
topRightControlPoints.last,
Vector2(21, 17.2),
Vector2(30, 12.1),
Vector2(32, 10.2),
];
final mediumRightCurveShape = BezierCurveShape(
controlPoints: mediumRightControlPoints,
)..rotate(curveRotationAngle);
final mediumRightFixtureDef = FixtureDef(mediumRightCurveShape);
fixturesDefs.add(mediumRightFixtureDef);
final bottomLeftControlPoints = [
mediumLeftControlPoints.last,
Vector2(40, -1),
Vector2(48, 1.9),
Vector2(50.5, 2.5),
];
final bottomLeftCurveShape = BezierCurveShape(
controlPoints: bottomLeftControlPoints,
)..rotate(curveRotationAngle);
final bottomLeftFixtureDef = FixtureDef(bottomLeftCurveShape);
fixturesDefs.add(bottomLeftFixtureDef);
final bottomRightControlPoints = [
mediumRightControlPoints.last,
Vector2(40, 4),
Vector2(46, 6.5),
Vector2(48.8, 7.6),
];
final bottomRightCurveShape = BezierCurveShape(
controlPoints: bottomRightControlPoints,
)..rotate(curveRotationAngle);
final bottomRightFixtureDef = FixtureDef(bottomRightCurveShape);
fixturesDefs.add(bottomRightFixtureDef);
final exitWall = ArcShape(
center: exitPoint,
arcRadius: width / 2,
angle: math.pi,
rotation: exitRotationAngle,
);
final exitFixtureDef = FixtureDef(exitWall);
fixturesDefs.add(exitFixtureDef);
return fixturesDefs;
}
@override
Body createBody() {
final bodyDef = BodyDef()
..userData = this
..position = initialPosition;
final body = world.createBody(bodyDef);
_createFixtureDefs().forEach(body.createFixture);
return body;
}
}
/// {@template spaceship_exit_rail_end}
/// A sensor [BodyComponent] responsible for sending the [Ball]
/// back to the board.
/// {@endtemplate}
class SpaceshipExitRailEnd extends RampOpening {
/// {@macro spaceship_exit_rail_end}
SpaceshipExitRailEnd()
: super(
pathwayLayer: Layer.spaceshipExitRail,
orientation: RampOrientation.down,
) {
layer = Layer.spaceshipExitRail;
}
@override
Shape get shape {
return CircleShape()..radius = 1;
}
}
/// [ContactCallback] that handles the contact between the [Ball]
/// and a [SpaceshipExitRailEnd].
///
/// It resets the [Ball] priority and filter data so it will "be back" on the
/// board.
class SpaceshipExitRailEndBallContactCallback
extends ContactCallback<SpaceshipExitRailEnd, Ball> {
@override
void begin(SpaceshipExitRailEnd exitRail, Ball ball, _) {
ball
..priority = 1
..gameRef.reorderChildren()
..layer = exitRail.outsideLayer;
}
}

@ -53,6 +53,13 @@ class PinballGame extends Forge2DGame
),
),
);
unawaited(
addFromBlueprint(
SpaceshipExitRail(
position: Vector2(-34.3, 23.8),
),
),
);
// Fix camera on the center of the board.
camera

@ -61,6 +61,9 @@ enum Layer {
/// Collide only with Spaceship group elements.
spaceship,
/// Collide only with Spaceship exit rail group elements.
spaceshipExitRail,
}
/// {@template layer_mask_bits}
@ -89,6 +92,8 @@ extension LayerMaskBits on Layer {
return 0x0005;
case Layer.spaceship:
return 0x000A;
case Layer.spaceshipExitRail:
return 0x0004;
}
}
}

@ -32,7 +32,10 @@ class Spaceship extends Forge2DBlueprint {
SpaceshipSaucer()..initialPosition = position,
SpaceshipEntrance()..initialPosition = position,
AndroidHead()..initialPosition = position,
SpaceshipHole()..initialPosition = position - Vector2(5.2, 4.8),
SpaceshipHole(
onExitLayer: Layer.spaceshipExitRail,
onExitElevation: 2,
)..initialPosition = position - Vector2(5.2, 4.8),
SpaceshipHole()..initialPosition = position - Vector2(-7.2, 0.8),
SpaceshipWall()..initialPosition = position,
]);
@ -44,7 +47,8 @@ class Spaceship extends Forge2DBlueprint {
/// {@endtemplate}
class SpaceshipSaucer extends BodyComponent with InitialPosition, Layered {
/// {@macro spaceship_saucer}
SpaceshipSaucer() : super(priority: 2) {
// TODO(ruimiguel): apply Elevated when PR merged.
SpaceshipSaucer() : super(priority: 3) {
layer = Layer.spaceship;
}
@ -88,7 +92,7 @@ class SpaceshipSaucer extends BodyComponent with InitialPosition, Layered {
/// {@endtemplate}
class AndroidHead extends BodyComponent with InitialPosition, Layered {
/// {@macro spaceship_bridge}
AndroidHead() : super(priority: 3) {
AndroidHead() : super(priority: 4) {
layer = Layer.spaceship;
}
@ -149,6 +153,10 @@ class SpaceshipEntrance extends RampOpening {
layer = Layer.spaceship;
}
/// Priority order for [SpaceshipHole] on enter.
// TODO(ruimiguel): apply Elevated when PR merged.
final int onEnterElevation = 4;
@override
Shape get shape {
renderBody = false;
@ -169,29 +177,31 @@ class SpaceshipEntrance extends RampOpening {
/// {@template spaceship_hole}
/// A sensor [BodyComponent] responsible for sending the [Ball]
/// back to the board.
/// out from the [Spaceship].
/// {@endtemplate}
class SpaceshipHole extends BodyComponent with InitialPosition, Layered {
class SpaceshipHole extends RampOpening {
/// {@macro spaceship_hole}
SpaceshipHole() {
SpaceshipHole({Layer? onExitLayer, this.onExitElevation = 1})
: super(
pathwayLayer: Layer.spaceship,
outsideLayer: onExitLayer,
orientation: RampOrientation.up,
) {
layer = Layer.spaceship;
}
@override
Body createBody() {
renderBody = false;
final shape = ArcShape(center: Vector2(-3.5, 2), arcRadius: 6, angle: 1);
/// Priority order for [SpaceshipHole] on exit.
// TODO(ruimiguel): apply Elevated when PR merged.
final int onExitElevation;
final bodyDef = BodyDef()
..userData = this
..position = initialPosition
..angle = 5.2
..type = BodyType.static;
return world.createBody(bodyDef)
..createFixture(
FixtureDef(shape)..isSensor = true,
);
@override
Shape get shape {
return ArcShape(
center: Vector2(0, 4.2),
arcRadius: 6,
angle: 1,
rotation: 60 * pi / 180,
);
}
}
@ -225,6 +235,7 @@ class _SpaceshipWallShape extends ChainShape {
/// {@endtemplate}
class SpaceshipWall extends BodyComponent with InitialPosition, Layered {
/// {@macro spaceship_wall}
// TODO(ruimiguel): apply Elevated when PR merged
SpaceshipWall() : super(priority: 4) {
layer = Layer.spaceship;
}
@ -258,7 +269,8 @@ class SpaceshipEntranceBallContactCallback
@override
void begin(SpaceshipEntrance entrance, Ball ball, _) {
ball
..priority = 3
// TODO(ruimiguel): apply Elevated when PR merged.
..priority = entrance.onEnterElevation
..gameRef.reorderChildren()
..layer = Layer.spaceship;
}
@ -267,15 +279,16 @@ class SpaceshipEntranceBallContactCallback
/// [ContactCallback] that handles the contact between the [Ball]
/// and a [SpaceshipHole].
///
/// It resets the [Ball] priority and filter data so it will "be back" on the
/// It sets the [Ball] priority and filter data so it will "be back" on the
/// board.
class SpaceshipHoleBallContactCallback
extends ContactCallback<SpaceshipHole, Ball> {
@override
void begin(SpaceshipHole hole, Ball ball, _) {
ball
..priority = 1
// TODO(ruimiguel): apply Elevated when PR merged.
..priority = hole.onExitElevation
..gameRef.reorderChildren()
..layer = Layer.board;
..layer = hole.outsideLayer;
}
}

@ -7,8 +7,8 @@ environment:
sdk: ">=2.16.0 <3.0.0"
dependencies:
flame: ^1.1.0-releasecandidate.6
flame_forge2d: ^0.9.0-releasecandidate.6
flame: ^1.1.0
flame_forge2d: ^0.10.0
flutter:
sdk: flutter
geometry:
@ -16,7 +16,7 @@ dependencies:
dev_dependencies:
flame_test: ^1.1.0
flame_test: ^1.3.0
flutter_test:
sdk: flutter
mocktail: ^0.2.0

@ -91,14 +91,14 @@ packages:
name: flame
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-releasecandidate.6"
version: "1.1.0"
flame_forge2d:
dependency: "direct main"
description:
name: flame_forge2d
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0-releasecandidate.6"
version: "0.10.0"
flutter:
dependency: "direct main"
description: flutter
@ -134,7 +134,7 @@ packages:
name: forge2d
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
version: "0.10.0"
freezed_annotation:
dependency: transitive
description:

@ -8,8 +8,8 @@ environment:
dependencies:
dashbook: ^0.1.7
flame: ^1.1.0-releasecandidate.6
flame_forge2d: ^0.9.0-releasecandidate.6
flame: ^1.1.0
flame_forge2d: ^0.10.0
flutter:
sdk: flutter
pinball_components:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 78 KiB

@ -1,6 +1,5 @@
// ignore_for_file: cascade_invocations
import 'package:flame/game.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
@ -39,38 +38,40 @@ void main() {
});
group('Spaceship', () {
testWidgets('renders correctly', (tester) async {
final game = TestGame();
final tester = FlameTester(TestGame.new);
// TODO(erickzanardo): This should be handled by flame test.
// refctor it when https://github.com/flame-engine/flame/pull/1501 is merged
await tester.runAsync(() async {
await tester.pumpWidget(GameWidget(game: game));
await game.ready();
tester.testGameWidget(
'renders correctly',
setUp: (game, tester) async {
await game.addFromBlueprint(Spaceship(position: Vector2(30, -30)));
await game.ready();
await tester.pump();
});
await expectLater(
find.byGame<Forge2DGame>(),
matchesGoldenFile('golden/spaceship.png'),
);
});
},
verify: (game, tester) async {
await expectLater(
find.byGame<Forge2DGame>(),
matchesGoldenFile('golden/spaceship.png'),
);
},
);
});
group('SpaceshipEntranceBallContactCallback', () {
test('changes the ball priority on contact', () {
when(() => entrance.onEnterElevation).thenReturn(3);
SpaceshipEntranceBallContactCallback().begin(
entrance,
ball,
MockContact(),
);
verify(() => ball.priority = 3).called(1);
verify(() => ball.priority = entrance.onEnterElevation).called(1);
});
test('re order the game children', () {
when(() => entrance.onEnterElevation).thenReturn(3);
SpaceshipEntranceBallContactCallback().begin(
entrance,
ball,
@ -83,16 +84,22 @@ void main() {
group('SpaceshipHoleBallContactCallback', () {
test('changes the ball priority on contact', () {
when(() => hole.outsideLayer).thenReturn(Layer.board);
when(() => hole.onExitElevation).thenReturn(1);
SpaceshipHoleBallContactCallback().begin(
hole,
ball,
MockContact(),
);
verify(() => ball.priority = 1).called(1);
verify(() => ball.priority = hole.onExitElevation).called(1);
});
test('re order the game children', () {
when(() => hole.outsideLayer).thenReturn(Layer.board);
when(() => hole.onExitElevation).thenReturn(1);
SpaceshipHoleBallContactCallback().begin(
hole,
ball,

@ -182,28 +182,28 @@ packages:
name: flame
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-releasecandidate.6"
version: "1.1.0"
flame_bloc:
dependency: "direct main"
description:
name: flame_bloc
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0-releasecandidate.6"
version: "1.2.0"
flame_forge2d:
dependency: "direct main"
description:
name: flame_forge2d
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0-releasecandidate.6"
version: "0.10.0"
flame_test:
dependency: "direct dev"
description:
name: flame_test
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.3.0"
flutter:
dependency: "direct main"
description: flutter
@ -237,7 +237,7 @@ packages:
name: forge2d
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
version: "0.10.0"
frontend_server_client:
dependency: transitive
description:

@ -10,9 +10,9 @@ dependencies:
bloc: ^8.0.2
cloud_firestore: ^3.1.10
equatable: ^2.0.3
flame: ^1.1.0-releasecandidate.6
flame_bloc: ^1.2.0-releasecandidate.6
flame_forge2d: ^0.9.0-releasecandidate.6
flame: ^1.1.0
flame_bloc: ^1.2.0
flame_forge2d: ^0.10.0
flutter:
sdk: flutter
flutter_bloc: ^8.0.1
@ -30,7 +30,7 @@ dependencies:
dev_dependencies:
bloc_test: ^9.0.2
flame_test: ^1.1.0
flame_test: ^1.3.0
flutter_test:
sdk: flutter
mockingjay: ^0.2.0

@ -27,11 +27,12 @@ void main() {
final tester = flameBlocTester(gameBloc: () => gameBloc);
tester.widgetTest(
tester.testGameWidget(
'adds BallLost to GameBloc',
(game, tester) async {
setUp: (game, tester) async {
await game.ready();
},
verify: (game, tester) async {
game.children.whereType<Ball>().first.controller.lost();
await tester.pump();
@ -39,14 +40,15 @@ void main() {
},
);
tester.widgetTest(
tester.testGameWidget(
'resets the ball if the game is not over',
(game, tester) async {
setUp: (game, tester) async {
await game.ready();
game.children.whereType<Ball>().first.controller.lost();
await game.ready(); // Making sure that all additions are done
},
verify: (game, tester) async {
expect(
game.children.whereType<Ball>().length,
equals(1),
@ -54,9 +56,9 @@ void main() {
},
);
tester.widgetTest(
tester.testGameWidget(
'no ball is added on game over',
(game, tester) async {
setUp: (game, tester) async {
whenListen(
gameBloc,
const Stream<GameState>.empty(),
@ -72,7 +74,8 @@ void main() {
game.children.whereType<Ball>().first.controller.lost();
await tester.pump();
},
verify: (game, tester) async {
expect(
game.children.whereType<Ball>().length,
equals(0),

@ -205,22 +205,24 @@ void main() {
);
});
tester.widgetTest(
tester.testGameWidget(
'adds BonusLetterActivated to GameBloc when not activated',
(game, tester) async {
setUp: (game, tester) async {
await game.ready();
final bonusLetter = game.descendants().whereType<BonusLetter>().first;
bonusLetter.activate();
await game.ready();
await tester.pump();
},
verify: (game, tester) async {
verify(() => gameBloc.add(const BonusLetterActivated(0))).called(1);
},
);
tester.widgetTest(
tester.testGameWidget(
"doesn't add BonusLetterActivated to GameBloc when already activated",
(game, tester) async {
setUp: (game, tester) async {
const state = GameState(
score: 0,
balls: 2,
@ -238,14 +240,15 @@ void main() {
final bonusLetter = game.descendants().whereType<BonusLetter>().first;
bonusLetter.activate();
await game.ready();
},
verify: (game, tester) async {
verifyNever(() => gameBloc.add(const BonusLetterActivated(0)));
},
);
tester.widgetTest(
tester.testGameWidget(
'adds a ColorEffect',
(game, tester) async {
setUp: (game, tester) async {
const state = GameState(
score: 0,
balls: 2,
@ -260,7 +263,9 @@ void main() {
bonusLetter.onNewState(state);
await tester.pump();
},
verify: (game, tester) async {
final bonusLetter = game.descendants().whereType<BonusLetter>().first;
expect(
bonusLetter.children.whereType<ColorEffect>().length,
equals(1),
@ -268,9 +273,14 @@ void main() {
},
);
tester.widgetTest(
tester.testGameWidget(
'only listens when there is a change on the letter status',
(game, tester) async {
setUp: (game, tester) async {
await game.ready();
final bonusLetter = game.descendants().whereType<BonusLetter>().first;
bonusLetter.activate();
},
verify: (game, tester) async {
const state = GameState(
score: 0,
balls: 2,
@ -278,11 +288,7 @@ void main() {
activatedDashNests: {},
bonusHistory: [],
);
await game.ready();
final bonusLetter = game.descendants().whereType<BonusLetter>().first;
bonusLetter.activate();
expect(
bonusLetter.listenWhen(const GameState.initial(), state),
isTrue,

@ -30,8 +30,6 @@ void main() {
'a FlutterSignPost',
(game) async {
await game.ready();
final flutterForest = FlutterForest();
await game.ensureAdd(flutterForest);
expect(
game.descendants().whereType<FlutterSignPost>().length,
@ -71,10 +69,12 @@ void main() {
);
});
tester.widgetTest(
tester.testGameWidget(
'listens when a Bonus.dashNest is added',
(game, tester) async {
setUp: (game, tester) async {
await game.ready();
},
verify: (game, tester) async {
final flutterForest =
game.descendants().whereType<FlutterForest>().first;
@ -85,7 +85,6 @@ void main() {
activatedDashNests: {},
bonusHistory: [GameBonus.dashNest],
);
expect(
flutterForest.listenWhen(const GameState.initial(), state),
isTrue,
@ -107,15 +106,16 @@ void main() {
);
});
tester.widgetTest(
final dashNestBumper = MockDashNestBumper();
tester.testGameWidget(
'adds a DashNestActivated event with DashNestBumper.id',
(game, tester) async {
final contactCallback = DashNestBumperBallContactCallback();
setUp: (game, tester) async {
const id = '0';
final dashNestBumper = MockDashNestBumper();
when(() => dashNestBumper.id).thenReturn(id);
when(() => dashNestBumper.gameRef).thenReturn(game);
},
verify: (game, tester) async {
final contactCallback = DashNestBumperBallContactCallback();
contactCallback.begin(dashNestBumper, MockBall(), MockContact());
verify(() => gameBloc.add(DashNestActivated(dashNestBumper.id)))

@ -233,7 +233,7 @@ void main() {
plunger: plunger,
anchor: anchor,
);
game.world.createJoint(jointDef);
game.world.createJoint(PrismaticJoint(jointDef));
expect(jointDef.bodyB, equals(anchor.body));
},
@ -250,7 +250,7 @@ void main() {
plunger: plunger,
anchor: anchor,
);
game.world.createJoint(jointDef);
game.world.createJoint(PrismaticJoint(jointDef));
expect(jointDef.enableLimit, isTrue);
},
@ -267,7 +267,7 @@ void main() {
plunger: plunger,
anchor: anchor,
);
game.world.createJoint(jointDef);
game.world.createJoint(PrismaticJoint(jointDef));
expect(jointDef.lowerTranslation, equals(double.negativeInfinity));
},
@ -284,7 +284,7 @@ void main() {
plunger: plunger,
anchor: anchor,
);
game.world.createJoint(jointDef);
game.world.createJoint(PrismaticJoint(jointDef));
expect(jointDef.collideConnected, isTrue);
},
@ -292,11 +292,11 @@ void main() {
});
testRawKeyUpEvents([LogicalKeyboardKey.space], (event) {
flameTester.widgetTest(
late final anchor = PlungerAnchor(plunger: plunger);
flameTester.testGameWidget(
'plunger cannot go below anchor',
(game, tester) async {
setUp: (game, tester) async {
await game.ensureAdd(plunger);
final anchor = PlungerAnchor(plunger: plunger);
await game.ensureAdd(anchor);
// Giving anchor a shape for the plunger to collide with.
@ -306,19 +306,20 @@ void main() {
plunger: plunger,
anchor: anchor,
);
game.world.createJoint(jointDef);
game.world.createJoint(PrismaticJoint(jointDef));
await tester.pump(const Duration(seconds: 1));
},
verify: (game, tester) async {
expect(plunger.body.position.y > anchor.body.position.y, isTrue);
},
);
});
testRawKeyUpEvents([LogicalKeyboardKey.space], (event) {
flameTester.widgetTest(
flameTester.testGameWidget(
'plunger cannot excessively exceed starting position',
(game, tester) async {
setUp: (game, tester) async {
await game.ensureAdd(plunger);
final anchor = PlungerAnchor(plunger: plunger);
await game.ensureAdd(anchor);
@ -327,12 +328,13 @@ void main() {
plunger: plunger,
anchor: anchor,
);
game.world.createJoint(jointDef);
game.world.createJoint(PrismaticJoint(jointDef));
plunger.body.setTransform(Vector2(0, -1), 0);
await tester.pump(const Duration(seconds: 1));
},
verify: (game, tester) async {
expect(plunger.body.position.y < 1, isTrue);
},
);

@ -0,0 +1,60 @@
import 'package:flame_forge2d/flame_forge2d.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('SpaceshipExitRail', () {
late PinballGame game;
late SpaceshipExitRailEnd exitRailEnd;
late Ball ball;
late Body body;
late Fixture fixture;
late Filter filterData;
setUp(() {
game = MockPinballGame();
exitRailEnd = MockSpaceshipExitRailEnd();
ball = MockBall();
body = MockBody();
when(() => ball.gameRef).thenReturn(game);
when(() => ball.body).thenReturn(body);
fixture = MockFixture();
filterData = MockFilter();
when(() => body.fixtures).thenReturn([fixture]);
when(() => fixture.filterData).thenReturn(filterData);
});
group('SpaceshipExitHoleBallContactCallback', () {
test('changes the ball priority on contact', () {
when(() => exitRailEnd.outsideLayer).thenReturn(Layer.board);
SpaceshipExitRailEndBallContactCallback().begin(
exitRailEnd,
ball,
MockContact(),
);
verify(() => ball.priority = 1).called(1);
});
test('reorders the game children', () {
when(() => exitRailEnd.outsideLayer).thenReturn(Layer.board);
SpaceshipExitRailEndBallContactCallback().begin(
exitRailEnd,
ball,
MockContact(),
);
verify(game.reorderChildren).called(1);
});
});
});
}

@ -70,6 +70,8 @@ class MockSpaceshipEntrance extends Mock implements SpaceshipEntrance {}
class MockSpaceshipHole extends Mock implements SpaceshipHole {}
class MockSpaceshipExitRailEnd extends Mock implements SpaceshipExitRailEnd {}
class MockComponentSet extends Mock implements ComponentSet {}
class MockDashNestBumper extends Mock implements DashNestBumper {}

Loading…
Cancel
Save