feat: spaceship drop assets (#110)

* feat: added assets for drop rail

* feat: placed assets and base bodies

* feat: assets and bases

* refactor: hide spaceship hole

* refactor: redimension curves

* fix: lint

* test: fix geometry tests

* refactor: tube to fit spaceship opening

* refactor: applied priority changes to drop tube

* test: fixed tests for ball contact with exit rail

* Update test/game/components/spaceship_exit_rail_test.dart

Co-authored-by: Alejandro Santiago <dev@alestiago.com>

* chore: formatted test file

Co-authored-by: Allison Ryan <allisonryan0002@gmail.com>
Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>
Co-authored-by: Alejandro Santiago <dev@alestiago.com>
pull/131/head
Rui Miguel Alonso 2 years ago committed by GitHub
parent e6fd5f90fa
commit c8bc7c1942
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

@ -1,10 +1,10 @@
// ignore_for_file: avoid_renaming_method_parameters // ignore_for_file: avoid_renaming_method_parameters
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui';
import 'package:flame/extensions.dart'; import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/gen/assets.gen.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets; import 'package:pinball_components/pinball_components.dart' hide Assets;
/// {@template spaceship_exit_rail} /// {@template spaceship_exit_rail}
@ -12,10 +12,10 @@ import 'package:pinball_components/pinball_components.dart' hide Assets;
/// {@endtemplate} /// {@endtemplate}
class SpaceshipExitRail extends Forge2DBlueprint { class SpaceshipExitRail extends Forge2DBlueprint {
/// {@macro spaceship_exit_rail} /// {@macro spaceship_exit_rail}
SpaceshipExitRail({required this.position}); SpaceshipExitRail();
/// The [position] where the elements will be created /// Base priority for wall while be on jetpack ramp.
final Vector2 position; static const ballPriorityWhenOnSpaceshipExitRail = 2;
@override @override
void build(_) { void build(_) {
@ -23,127 +23,101 @@ class SpaceshipExitRail extends Forge2DBlueprint {
SpaceshipExitRailEndBallContactCallback(), SpaceshipExitRailEndBallContactCallback(),
]); ]);
final spaceshipExitRailRamp = _SpaceshipExitRailRamp() final exitRailRamp = _SpaceshipExitRailRamp();
..initialPosition = position; final exitRailEnd = SpaceshipExitRailEnd();
final exitRail = SpaceshipExitRailEnd() final topBase = _SpaceshipExitRailBase(radius: 0.55)
..initialPosition = position + _SpaceshipExitRailRamp.exitPoint; ..initialPosition = Vector2(-26.15, 18.65);
final bottomBase = _SpaceshipExitRailBase(radius: 0.8)
..initialPosition = Vector2(-25.5, -12.9);
addAll([ addAll([
spaceshipExitRailRamp, exitRailRamp,
exitRail, exitRailEnd,
topBase,
bottomBase,
]); ]);
} }
} }
class _SpaceshipExitRailRamp extends BodyComponent class _SpaceshipExitRailRamp extends BodyComponent
with InitialPosition, Layered { with InitialPosition, Layered {
_SpaceshipExitRailRamp() : super(priority: 2) { _SpaceshipExitRailRamp()
: super(
priority: SpaceshipExitRail.ballPriorityWhenOnSpaceshipExitRail - 1,
) {
renderBody = false;
layer = Layer.spaceshipExitRail; 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() { 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 fixturesDefs = <FixtureDef>[];
final entranceWall = ArcShape( final topArcShape = ArcShape(
center: Vector2(width / 2, 0), center: Vector2(-35.5, 30.9),
arcRadius: width / 2, arcRadius: 2.5,
angle: math.pi, angle: math.pi,
rotation: entranceRotationAngle, rotation: 2.9,
); );
final entranceFixtureDef = FixtureDef(entranceWall); final topArcFixtureDef = FixtureDef(topArcShape);
fixturesDefs.add(entranceFixtureDef); fixturesDefs.add(topArcFixtureDef);
final topLeftControlPoints = [
Vector2(0, 0),
Vector2(10, .5),
Vector2(7, 4),
Vector2(15.5, 8.3),
];
final topLeftCurveShape = BezierCurveShape( final topLeftCurveShape = BezierCurveShape(
controlPoints: topLeftControlPoints, controlPoints: [
)..rotate(curveRotationAngle); Vector2(-37.9, 30.4),
final topLeftFixtureDef = FixtureDef(topLeftCurveShape); Vector2(-38, 23.9),
fixturesDefs.add(topLeftFixtureDef); Vector2(-30.93, 18.2),
],
final topRightControlPoints = [ );
Vector2(0, width), final topLeftCurveFixtureDef = FixtureDef(topLeftCurveShape);
Vector2(10, 6.5), fixturesDefs.add(topLeftCurveFixtureDef);
Vector2(7, 10),
Vector2(15.5, 13.2), final middleLeftCurveShape = BezierCurveShape(
]; controlPoints: [
final topRightCurveShape = BezierCurveShape( Vector2(-30.93, 18.2),
controlPoints: topRightControlPoints, Vector2(-22.6, 10.3),
)..rotate(curveRotationAngle); Vector2(-30, 0.2),
final topRightFixtureDef = FixtureDef(topRightCurveShape); ],
fixturesDefs.add(topRightFixtureDef); );
final middleLeftCurveFixtureDef = FixtureDef(middleLeftCurveShape);
final mediumLeftControlPoints = [ fixturesDefs.add(middleLeftCurveFixtureDef);
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( final bottomLeftCurveShape = BezierCurveShape(
controlPoints: bottomLeftControlPoints, controlPoints: [
)..rotate(curveRotationAngle); Vector2(-30, 0.2),
final bottomLeftFixtureDef = FixtureDef(bottomLeftCurveShape); Vector2(-36, -8.6),
fixturesDefs.add(bottomLeftFixtureDef); Vector2(-32.04, -18.3),
],
final bottomRightControlPoints = [ );
mediumRightControlPoints.last, final bottomLeftCurveFixtureDef = FixtureDef(bottomLeftCurveShape);
Vector2(40, 4), fixturesDefs.add(bottomLeftCurveFixtureDef);
Vector2(46, 6.5),
Vector2(48.8, 7.6), final topRightStraightShape = EdgeShape()
]; ..set(
Vector2(-33, 31.3),
Vector2(-27.2, 21.3),
);
final topRightStraightFixtureDef = FixtureDef(topRightStraightShape);
fixturesDefs.add(topRightStraightFixtureDef);
final middleRightCurveShape = BezierCurveShape(
controlPoints: [
Vector2(-27.2, 21.3),
Vector2(-16.5, 11.4),
Vector2(-25.29, -1.7),
],
);
final middleRightCurveFixtureDef = FixtureDef(middleRightCurveShape);
fixturesDefs.add(middleRightCurveFixtureDef);
final bottomRightCurveShape = BezierCurveShape( final bottomRightCurveShape = BezierCurveShape(
controlPoints: bottomRightControlPoints, controlPoints: [
)..rotate(curveRotationAngle); Vector2(-25.29, -1.7),
final bottomRightFixtureDef = FixtureDef(bottomRightCurveShape); Vector2(-29.91, -8.5),
fixturesDefs.add(bottomRightFixtureDef); Vector2(-26.8, -15.7),
],
final exitWall = ArcShape(
center: exitPoint,
arcRadius: width / 2,
angle: math.pi,
rotation: exitRotationAngle,
); );
final exitFixtureDef = FixtureDef(exitWall); final bottomRightCurveFixtureDef = FixtureDef(bottomRightCurveShape);
fixturesDefs.add(exitFixtureDef); fixturesDefs.add(bottomRightCurveFixtureDef);
return fixturesDefs; return fixturesDefs;
} }
@ -159,6 +133,52 @@ class _SpaceshipExitRailRamp extends BodyComponent
return body; return body;
} }
@override
Future<void> onLoad() async {
await super.onLoad();
await _loadSprite();
}
Future<void> _loadSprite() async {
final sprite = await gameRef.loadSprite(
Assets.images.components.spaceshipDropTube.path,
);
final spriteComponent = SpriteComponent(
sprite: sprite,
size: Vector2(17.5, 55.7),
anchor: Anchor.center,
position: Vector2(-29.4, -5.7),
);
await add(spriteComponent);
}
}
class _SpaceshipExitRailBase extends BodyComponent
with InitialPosition, Layered {
_SpaceshipExitRailBase({required this.radius})
: super(
priority: SpaceshipExitRail.ballPriorityWhenOnSpaceshipExitRail + 1,
) {
renderBody = false;
layer = Layer.board;
}
final double radius;
@override
Body createBody() {
final shape = CircleShape()..radius = radius;
final fixtureDef = FixtureDef(shape);
final bodyDef = BodyDef()
..position = initialPosition
..userData = this;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
} }
/// {@template spaceship_exit_rail_end} /// {@template spaceship_exit_rail_end}
@ -172,12 +192,18 @@ class SpaceshipExitRailEnd extends RampOpening {
insideLayer: Layer.spaceshipExitRail, insideLayer: Layer.spaceshipExitRail,
orientation: RampOrientation.down, orientation: RampOrientation.down,
) { ) {
renderBody = false;
layer = Layer.spaceshipExitRail; layer = Layer.spaceshipExitRail;
} }
@override @override
Shape get shape { Shape get shape {
return CircleShape()..radius = 1; return ArcShape(
center: Vector2(-29, -17.8),
arcRadius: 2.5,
angle: math.pi * 0.8,
rotation: -0.16,
);
} }
} }
@ -191,8 +217,7 @@ class SpaceshipExitRailEndBallContactCallback
@override @override
void begin(SpaceshipExitRailEnd exitRail, Ball ball, _) { void begin(SpaceshipExitRailEnd exitRail, Ball ball, _) {
ball ball
..priority = 1 ..sendTo(exitRail.outsidePriority)
..gameRef.reorderChildren()
..layer = exitRail.outsideLayer; ..layer = exitRail.outsideLayer;
} }
} }

@ -22,6 +22,7 @@ extension PinballGameAssetsX on PinballGame {
images.load(components.Assets.images.dashBumper.main.active.keyName), images.load(components.Assets.images.dashBumper.main.active.keyName),
images.load(components.Assets.images.dashBumper.main.inactive.keyName), images.load(components.Assets.images.dashBumper.main.inactive.keyName),
images.load(Assets.images.components.background.path), images.load(Assets.images.components.background.path),
images.load(Assets.images.components.spaceshipDropTube.path),
]); ]);
} }
} }

@ -45,9 +45,7 @@ class PinballGame extends Forge2DGame
); );
unawaited( unawaited(
addFromBlueprint( addFromBlueprint(
SpaceshipExitRail( SpaceshipExitRail(),
position: Vector2(-34.3, 23.8),
),
), ),
); );

@ -20,6 +20,10 @@ class $AssetsImagesComponentsGen {
/// File path: assets/images/components/background.png /// File path: assets/images/components/background.png
AssetGenImage get background => AssetGenImage get background =>
const AssetGenImage('assets/images/components/background.png'); const AssetGenImage('assets/images/components/background.png');
/// File path: assets/images/components/spaceship-drop-tube.png
AssetGenImage get spaceshipDropTube =>
const AssetGenImage('assets/images/components/spaceship-drop-tube.png');
} }
class Assets { class Assets {

@ -114,9 +114,9 @@ void main() {
Vector2(0, 0), Vector2(0, 0),
Vector2(10, 10), Vector2(10, 10),
], ],
step: 0.001, step: 0.02,
); );
expect(points.length, 1000); expect(points.length, 50);
}); });
}); });

@ -195,8 +195,8 @@ class SpaceshipHole extends RampOpening {
@override @override
Shape get shape { Shape get shape {
return ArcShape( return ArcShape(
center: Vector2(0, 4.2), center: Vector2(0, 3.2),
arcRadius: 6, arcRadius: 5,
angle: 1, angle: 1,
rotation: 60 * pi / 180, rotation: 60 * pi / 180,
); );

@ -31,29 +31,33 @@ void main() {
when(() => fixture.filterData).thenReturn(filterData); when(() => fixture.filterData).thenReturn(filterData);
}); });
// TODO(alestiago): Make ContactCallback private and use `beginContact`
// instead.
group('SpaceshipExitHoleBallContactCallback', () { group('SpaceshipExitHoleBallContactCallback', () {
test('changes the ball priority on contact', () { setUp(() {
when(() => ball.priority).thenReturn(1);
when(() => exitRailEnd.outsideLayer).thenReturn(Layer.board); when(() => exitRailEnd.outsideLayer).thenReturn(Layer.board);
when(() => exitRailEnd.outsidePriority).thenReturn(0);
});
test('changes the ball priority on contact', () {
SpaceshipExitRailEndBallContactCallback().begin( SpaceshipExitRailEndBallContactCallback().begin(
exitRailEnd, exitRailEnd,
ball, ball,
MockContact(), MockContact(),
); );
verify(() => ball.priority = 1).called(1); verify(() => ball.sendTo(exitRailEnd.outsidePriority)).called(1);
}); });
test('reorders the game children', () { test('changes the ball layer on contact', () {
when(() => exitRailEnd.outsideLayer).thenReturn(Layer.board);
SpaceshipExitRailEndBallContactCallback().begin( SpaceshipExitRailEndBallContactCallback().begin(
exitRailEnd, exitRailEnd,
ball, ball,
MockContact(), MockContact(),
); );
verify(game.reorderChildren).called(1); verify(() => ball.layer = exitRailEnd.outsideLayer).called(1);
}); });
}); });
}); });

Loading…
Cancel
Save