Merge branch 'main' into refactor/position-exit-rail

pull/135/head
Allison Ryan 4 years ago
commit d139ae7914

@ -3,9 +3,6 @@ export 'bonus_word.dart';
export 'controlled_ball.dart';
export 'controlled_flipper.dart';
export 'flutter_forest.dart';
export 'jetpack_ramp.dart';
export 'launcher_ramp.dart';
export 'plunger.dart';
export 'score_points.dart';
export 'spaceship_exit_rail.dart';
export 'wall.dart';

@ -1,142 +0,0 @@
// ignore_for_file: public_member_api_docs, avoid_renaming_method_parameters
import 'dart:math' as math;
import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
/// A [Blueprint] which creates the [LauncherRamp].
class Launcher extends Forge2DBlueprint {
@override
void build(_) {
final position = Vector2(
BoardDimensions.bounds.right - 31.3,
BoardDimensions.bounds.bottom + 33,
);
addAllContactCallback([
RampOpeningBallContactCallback<_LauncherRampOpening>(),
]);
final leftOpening = _LauncherRampOpening(rotation: math.pi / 2)
..initialPosition = position + Vector2(-11.8, 72.7)
..layer = Layer.opening;
final rightOpening = _LauncherRampOpening(rotation: 0)
..initialPosition = position + Vector2(-5.4, 65.4)
..layer = Layer.opening;
final launcherRamp = LauncherRamp()
..initialPosition = position + Vector2(1.7, 0)
..layer = Layer.launcher;
addAll([
leftOpening,
rightOpening,
launcherRamp,
]);
}
}
/// {@template launcher_ramp}
/// The yellow right ramp, where the [Ball] goes through when launched from the
/// [Plunger].
/// {@endtemplate}
class LauncherRamp extends BodyComponent with InitialPosition, Layered {
/// {@macro launcher_ramp}
LauncherRamp() : super(priority: 2) {
layer = Layer.launcher;
paint = Paint()
..color = const Color.fromARGB(255, 251, 255, 0)
..style = PaintingStyle.stroke;
}
/// Width between walls of the ramp.
static const width = 5.0;
/// Radius of the external arc at the top of the ramp.
static const _externalRadius = 16.3;
List<FixtureDef> _createFixtureDefs() {
final fixturesDef = <FixtureDef>[];
final startPosition = initialPosition + Vector2(0, 3);
final endPosition = initialPosition + Vector2(0, 130);
final rightStraightShape = EdgeShape()
..set(
startPosition..rotate(BoardDimensions.perspectiveAngle),
endPosition..rotate(BoardDimensions.perspectiveAngle),
);
final rightStraightFixtureDef = FixtureDef(rightStraightShape);
fixturesDef.add(rightStraightFixtureDef);
final leftStraightShape = EdgeShape()
..set(
startPosition - Vector2(width, 0),
endPosition - Vector2(width, 0),
);
final leftStraightFixtureDef = FixtureDef(leftStraightShape);
fixturesDef.add(leftStraightFixtureDef);
final externalCurveShape = ArcShape(
center: initialPosition + Vector2(-28.2, 132),
arcRadius: _externalRadius,
angle: math.pi / 2,
rotation: 3 * math.pi / 2,
);
final externalCurveFixtureDef = FixtureDef(externalCurveShape);
fixturesDef.add(externalCurveFixtureDef);
final internalCurveShape = externalCurveShape.copyWith(
arcRadius: _externalRadius - width,
);
final internalCurveFixtureDef = FixtureDef(internalCurveShape);
fixturesDef.add(internalCurveFixtureDef);
return fixturesDef;
}
@override
Body createBody() {
final bodyDef = BodyDef()
..userData = this
..position = initialPosition;
final body = world.createBody(bodyDef);
_createFixtureDefs().forEach(body.createFixture);
return body;
}
}
/// {@template launcher_ramp_opening}
/// [RampOpening] with [Layer.launcher] to filter [Ball]s collisions
/// inside [LauncherRamp].
/// {@endtemplate}
class _LauncherRampOpening extends RampOpening {
/// {@macro launcher_ramp_opening}
_LauncherRampOpening({
required double rotation,
}) : _rotation = rotation,
super(
insideLayer: Layer.launcher,
orientation: RampOrientation.down,
insidePriority: 3,
);
final double _rotation;
static final Vector2 _size = Vector2(LauncherRamp.width / 3, .1);
@override
Shape get shape => PolygonShape()
..setAsBox(
_size.x,
_size.y,
initialPosition,
_rotation,
);
}

@ -1,5 +1,6 @@
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pinball_components/pinball_components.dart';
@ -13,7 +14,11 @@ class Plunger extends BodyComponent with KeyboardHandler, InitialPosition {
/// {@macro plunger}
Plunger({
required this.compressionDistance,
});
}) : super(
priority: 5,
// TODO(allisonryan0002): remove paint after asset is added.
paint: Paint()..color = const Color.fromARGB(255, 241, 8, 8),
);
/// Distance the plunger can lower.
final double compressionDistance;

@ -13,6 +13,12 @@ extension PinballGameAssetsX on PinballGame {
images.load(components.Assets.images.flipper.right.keyName),
images.load(components.Assets.images.baseboard.left.keyName),
images.load(components.Assets.images.baseboard.right.keyName),
images.load(components.Assets.images.spaceshipSaucer.keyName),
images.load(components.Assets.images.spaceshipBridge.keyName),
images.load(components.Assets.images.launchRamp.ramp.keyName),
images.load(
components.Assets.images.launchRamp.foregroundRailing.keyName,
),
images.load(components.Assets.images.dino.dinoLandTop.keyName),
images.load(components.Assets.images.dino.dinoLandBottom.keyName),
images.load(components.Assets.images.dashBumper.a.active.keyName),
@ -21,11 +27,19 @@ extension PinballGameAssetsX on PinballGame {
images.load(components.Assets.images.dashBumper.b.inactive.keyName),
images.load(components.Assets.images.dashBumper.main.active.keyName),
images.load(components.Assets.images.dashBumper.main.inactive.keyName),
images.load(components.Assets.images.spaceshipRamp.spaceshipRamp.keyName),
images.load(
components.Assets.images.spaceshipRamp.spaceshipRailingBg.keyName,
),
images.load(
components.Assets.images.spaceshipRamp.spaceshipRailingFg.keyName,
),
images.load(
components.Assets.images.spaceshipRamp.spaceshipDropTube.keyName,
),
images.load(components.Assets.images.chromeDino.mouth.keyName),
images.load(components.Assets.images.chromeDino.head.keyName),
images.load(Assets.images.components.background.path),
images.load(Assets.images.components.spaceshipRamp.path),
images.load(Assets.images.components.spaceshipRailingBg.path),
images.load(Assets.images.components.spaceshipRailingFg.path),
images.load(Assets.images.components.spaceshipDropTube.path),
images.load(Assets.images.components.spaceshipDropTubeFront.path),
]);
}

@ -35,7 +35,7 @@ class PinballGame extends Forge2DGame
unawaited(add(Board()));
unawaited(_addPlunger());
unawaited(_addBonusWord());
unawaited(_addPaths());
unawaited(_addRamps());
unawaited(
addFromBlueprint(
Spaceship(
@ -45,7 +45,7 @@ class PinballGame extends Forge2DGame
);
unawaited(
addFromBlueprint(
SpaceshipExitRail(),
SpaceshipRail(),
),
);
@ -91,11 +91,9 @@ class PinballGame extends Forge2DGame
);
}
Future<void> _addPaths() async {
unawaited(
addFromBlueprint(Jetpack()),
);
unawaited(addFromBlueprint(Launcher()));
Future<void> _addRamps() async {
unawaited(addFromBlueprint(SpaceshipRamp()));
unawaited(addFromBlueprint(LaunchRamp()));
}
void spawnBall() {
@ -130,7 +128,7 @@ class DebugPinballGame extends PinballGame with TapDetector {
anchor: Anchor.center,
)
..position = Vector2(0, -7.8)
..priority = -1;
..priority = -2;
await add(spriteComponent);
}

@ -20,26 +20,6 @@ class $AssetsImagesComponentsGen {
/// File path: assets/images/components/background.png
AssetGenImage get background =>
const AssetGenImage('assets/images/components/background.png');
/// File path: assets/images/components/spaceship-drop-tube-front.png
AssetGenImage get spaceshipDropTubeFront => const AssetGenImage(
'assets/images/components/spaceship-drop-tube-front.png');
/// File path: assets/images/components/spaceship-drop-tube.png
AssetGenImage get spaceshipDropTube =>
const AssetGenImage('assets/images/components/spaceship-drop-tube.png');
/// File path: assets/images/components/spaceship_railing_bg.png
AssetGenImage get spaceshipRailingBg =>
const AssetGenImage('assets/images/components/spaceship_railing_bg.png');
/// File path: assets/images/components/spaceship_railing_fg.png
AssetGenImage get spaceshipRailingFg =>
const AssetGenImage('assets/images/components/spaceship_railing_fg.png');
/// File path: assets/images/components/spaceship_ramp.png
AssetGenImage get spaceshipRamp =>
const AssetGenImage('assets/images/components/spaceship_ramp.png');
}
class Assets {

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

@ -14,6 +14,8 @@ class $AssetsImagesGen {
AssetGenImage get ball => const AssetGenImage('assets/images/ball.png');
$AssetsImagesBaseboardGen get baseboard => const $AssetsImagesBaseboardGen();
$AssetsImagesChromeDinoGen get chromeDino =>
const $AssetsImagesChromeDinoGen();
$AssetsImagesDashBumperGen get dashBumper =>
const $AssetsImagesDashBumperGen();
$AssetsImagesDinoGen get dino => const $AssetsImagesDinoGen();
@ -23,10 +25,16 @@ class $AssetsImagesGen {
AssetGenImage get flutterSignPost =>
const AssetGenImage('assets/images/flutter_sign_post.png');
$AssetsImagesLaunchRampGen get launchRamp =>
const $AssetsImagesLaunchRampGen();
/// File path: assets/images/spaceship_bridge.png
AssetGenImage get spaceshipBridge =>
const AssetGenImage('assets/images/spaceship_bridge.png');
$AssetsImagesSpaceshipRampGen get spaceshipRamp =>
const $AssetsImagesSpaceshipRampGen();
/// File path: assets/images/spaceship_saucer.png
AssetGenImage get spaceshipSaucer =>
const AssetGenImage('assets/images/spaceship_saucer.png');
@ -44,6 +52,18 @@ class $AssetsImagesBaseboardGen {
const AssetGenImage('assets/images/baseboard/right.png');
}
class $AssetsImagesChromeDinoGen {
const $AssetsImagesChromeDinoGen();
/// File path: assets/images/chrome_dino/head.png
AssetGenImage get head =>
const AssetGenImage('assets/images/chrome_dino/head.png');
/// File path: assets/images/chrome_dino/mouth.png
AssetGenImage get mouth =>
const AssetGenImage('assets/images/chrome_dino/mouth.png');
}
class $AssetsImagesDashBumperGen {
const $AssetsImagesDashBumperGen();
@ -77,6 +97,38 @@ class $AssetsImagesFlipperGen {
const AssetGenImage('assets/images/flipper/right.png');
}
class $AssetsImagesLaunchRampGen {
const $AssetsImagesLaunchRampGen();
/// File path: assets/images/launch_ramp/foreground-railing.png
AssetGenImage get foregroundRailing =>
const AssetGenImage('assets/images/launch_ramp/foreground-railing.png');
/// File path: assets/images/launch_ramp/ramp.png
AssetGenImage get ramp =>
const AssetGenImage('assets/images/launch_ramp/ramp.png');
}
class $AssetsImagesSpaceshipRampGen {
const $AssetsImagesSpaceshipRampGen();
/// File path: assets/images/spaceship_ramp/spaceship_drop_tube.png
AssetGenImage get spaceshipDropTube => const AssetGenImage(
'assets/images/spaceship_ramp/spaceship_drop_tube.png');
/// File path: assets/images/spaceship_ramp/spaceship_railing_bg.png
AssetGenImage get spaceshipRailingBg => const AssetGenImage(
'assets/images/spaceship_ramp/spaceship_railing_bg.png');
/// File path: assets/images/spaceship_ramp/spaceship_railing_fg.png
AssetGenImage get spaceshipRailingFg => const AssetGenImage(
'assets/images/spaceship_ramp/spaceship_railing_fg.png');
/// File path: assets/images/spaceship_ramp/spaceship_ramp.png
AssetGenImage get spaceshipRamp =>
const AssetGenImage('assets/images/spaceship_ramp/spaceship_ramp.png');
}
class $AssetsImagesDashBumperAGen {
const $AssetsImagesDashBumperAGen();

@ -11,7 +11,10 @@ export 'flutter_sign_post.dart';
export 'initial_position.dart';
export 'joint_anchor.dart';
export 'kicker.dart';
export 'launch_ramp.dart';
export 'layer.dart';
export 'ramp_opening.dart';
export 'shapes/shapes.dart';
export 'spaceship.dart';
export 'spaceship_rail.dart';
export 'spaceship_ramp.dart';

@ -0,0 +1,243 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball_components/pinball_components.dart';
/// {@template launch_ramp}
/// A [Blueprint] which creates the [_LaunchRampBase] and
/// [_LaunchRampForegroundRailing].
/// {@endtemplate}
class LaunchRamp extends Forge2DBlueprint {
@override
void build(_) {
addAllContactCallback([
RampOpeningBallContactCallback<_LaunchRampExit>(),
]);
final launchRampBase = _LaunchRampBase()..layer = Layer.launcher;
final launchRampForegroundRailing = _LaunchRampForegroundRailing()
..layer = Layer.launcher;
final launchRampExit = _LaunchRampExit(rotation: math.pi / 2)
..initialPosition = Vector2(1.8, 34.2)
..layer = Layer.opening
..renderBody = false;
addAll([
launchRampBase,
launchRampForegroundRailing,
launchRampExit,
]);
}
}
/// {@template launch_ramp_base}
/// Ramp the [Ball] is launched from at the beginning of each ball life.
/// {@endtemplate}
class _LaunchRampBase extends BodyComponent with InitialPosition, Layered {
/// {@macro launch_ramp_base}
_LaunchRampBase() : super(priority: -1) {
layer = Layer.launcher;
}
List<FixtureDef> _createFixtureDefs() {
final fixturesDef = <FixtureDef>[];
final rightStraightShape = EdgeShape()
..set(
Vector2(31.4, 61.4),
Vector2(46.5, -68.4),
);
final rightStraightFixtureDef = FixtureDef(rightStraightShape);
fixturesDef.add(rightStraightFixtureDef);
final leftStraightShape = EdgeShape()
..set(
Vector2(27.8, 61.4),
Vector2(41.5, -68.4),
);
final leftStraightFixtureDef = FixtureDef(leftStraightShape);
fixturesDef.add(leftStraightFixtureDef);
final topCurveShape = ArcShape(
center: Vector2(20.5, 61.1),
arcRadius: 11,
angle: 1.6,
rotation: -1.65,
);
final topCurveFixtureDef = FixtureDef(topCurveShape);
fixturesDef.add(topCurveFixtureDef);
final bottomCurveShape = ArcShape(
center: Vector2(19.3, 60.3),
arcRadius: 8.5,
angle: 1.48,
rotation: -1.58,
);
final bottomCurveFixtureDef = FixtureDef(bottomCurveShape);
fixturesDef.add(bottomCurveFixtureDef);
final topStraightShape = EdgeShape()
..set(
Vector2(3.7, 70.1),
Vector2(19.1, 72.1),
);
final topStraightFixtureDef = FixtureDef(topStraightShape);
fixturesDef.add(topStraightFixtureDef);
final bottomStraightShape = EdgeShape()
..set(
Vector2(3.7, 66.9),
Vector2(19.1, 68.8),
);
final bottomStraightFixtureDef = FixtureDef(bottomStraightShape);
fixturesDef.add(bottomStraightFixtureDef);
return fixturesDef;
}
@override
Body createBody() {
final bodyDef = BodyDef()
..userData = this
..position = initialPosition;
final body = world.createBody(bodyDef);
_createFixtureDefs().forEach(body.createFixture);
return body;
}
@override
Future<void> onLoad() async {
await super.onLoad();
await _loadSprite();
renderBody = false;
}
Future<void> _loadSprite() async {
final sprite = await gameRef.loadSprite(
Assets.images.launchRamp.ramp.keyName,
);
await add(
SpriteComponent(
sprite: sprite,
size: sprite.originalSize / 10,
anchor: Anchor.center,
position: Vector2(25.65, 0),
),
);
}
}
/// {@template launch_ramp_foreground_railing}
/// Foreground railing for the [_LaunchRampBase] to render in front of the
/// [Ball].
/// {@endtemplate}
class _LaunchRampForegroundRailing extends BodyComponent
with InitialPosition, Layered {
/// {@macro launch_ramp_foreground_railing}
_LaunchRampForegroundRailing() : super(priority: 4) {
layer = Layer.launcher;
}
List<FixtureDef> _createFixtureDefs() {
final fixturesDef = <FixtureDef>[];
final rightStraightShape = EdgeShape()
..set(
Vector2(27.6, 57.9),
Vector2(30, 35.1),
);
final rightStraightFixtureDef = FixtureDef(rightStraightShape);
fixturesDef.add(rightStraightFixtureDef);
final curveShape = ArcShape(
center: Vector2(20.1, 59.3),
arcRadius: 7.5,
angle: 1.8,
rotation: -1.63,
);
final curveFixtureDef = FixtureDef(curveShape);
fixturesDef.add(curveFixtureDef);
final topStraightShape = EdgeShape()
..set(
Vector2(3.7, 66.8),
Vector2(19.7, 66.8),
);
final topStraightFixtureDef = FixtureDef(topStraightShape);
fixturesDef.add(topStraightFixtureDef);
return fixturesDef;
}
@override
Body createBody() {
final bodyDef = BodyDef()
..userData = this
..position = initialPosition;
final body = world.createBody(bodyDef);
_createFixtureDefs().forEach(body.createFixture);
return body;
}
@override
Future<void> onLoad() async {
await super.onLoad();
await _loadSprite();
renderBody = false;
}
Future<void> _loadSprite() async {
final sprite = await gameRef.loadSprite(
Assets.images.launchRamp.foregroundRailing.keyName,
);
await add(
SpriteComponent(
sprite: sprite,
size: sprite.originalSize / 10,
anchor: Anchor.center,
position: Vector2(22.8, 0),
priority: 4,
),
);
}
}
/// {@template launch_ramp_exit}
/// [RampOpening] with [Layer.launcher] to filter [Ball]s exiting the
/// [LaunchRamp].
/// {@endtemplate}
class _LaunchRampExit extends RampOpening {
/// {@macro launch_ramp_exit}
_LaunchRampExit({
required double rotation,
}) : _rotation = rotation,
super(
insideLayer: Layer.launcher,
orientation: RampOrientation.down,
insidePriority: 3,
);
final double _rotation;
static final Vector2 _size = Vector2(1.6, 0.1);
@override
Shape get shape => PolygonShape()
..setAsBox(
_size.x,
_size.y,
initialPosition,
_rotation,
);
}

@ -53,8 +53,8 @@ enum Layer {
/// Collide only with ramps opening elements.
opening,
/// Collide only with Jetpack group elements.
jetpack,
/// Collide only with Spaceship entrance ramp group elements.
spaceshipEntranceRamp,
/// Collide only with Launcher group elements.
launcher,
@ -86,7 +86,7 @@ extension LayerMaskBits on Layer {
return 0x0001;
case Layer.opening:
return 0x0007;
case Layer.jetpack:
case Layer.spaceshipEntranceRamp:
return 0x0002;
case Layer.launcher:
return 0x0005;

@ -37,7 +37,7 @@ class Spaceship extends Forge2DBlueprint {
AndroidHead()..initialPosition = position,
SpaceshipHole(
outsideLayer: Layer.spaceshipExitRail,
outsidePriority: 2,
outsidePriority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail,
)..initialPosition = position - Vector2(5.2, 4.8),
SpaceshipHole()..initialPosition = position - Vector2(-7.2, 0.8),
SpaceshipWall()..initialPosition = position,

@ -4,48 +4,48 @@ import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/gen/assets.gen.dart';
import 'package:pinball_components/gen/assets.gen.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets;
/// {@template spaceship_exit_rail}
/// {@template spaceship_rail}
/// A [Blueprint] for the spaceship drop tube.
/// {@endtemplate}
class SpaceshipExitRail extends Forge2DBlueprint {
/// {@macro spaceship_exit_rail}
SpaceshipExitRail();
class SpaceshipRail extends Forge2DBlueprint {
/// {@macro spaceship_rail}
SpaceshipRail();
/// Base priority for wall while be on jetpack ramp.
static const ballPriorityWhenOnSpaceshipExitRail = 2;
/// Base priority for ball while be in [_SpaceshipRailRamp].
static const ballPriorityWhenOnSpaceshipRail = 2;
@override
void build(_) {
addAllContactCallback([
SpaceshipExitRailEndBallContactCallback(),
SpaceshipRailExitBallContactCallback(),
]);
final exitRailRamp = _SpaceshipExitRailRamp();
final exitRailEnd = SpaceshipExitRailEnd();
final topBase = _SpaceshipExitRailBase(radius: 0.55)
final railRamp = _SpaceshipRailRamp();
final railEnd = SpaceshipRailExit();
final topBase = _SpaceshipRailBase(radius: 0.55)
..initialPosition = Vector2(-26.15, 18.65);
final bottomBase = _SpaceshipExitRailBase(radius: 0.8)
final bottomBase = _SpaceshipRailBase(radius: 0.8)
..initialPosition = Vector2(-25.5, -12.9);
final exitRailForeground = _SpaceshipExitRailForeground();
final railForeground = _SpaceshipRailForeground();
addAll([
exitRailRamp,
exitRailEnd,
railRamp,
railEnd,
topBase,
bottomBase,
exitRailForeground,
railForeground,
]);
}
}
class _SpaceshipExitRailRamp extends BodyComponent
with InitialPosition, Layered {
_SpaceshipExitRailRamp()
/// Represents the spaceship drop rail from the [Spaceship].
class _SpaceshipRailRamp extends BodyComponent with InitialPosition, Layered {
_SpaceshipRailRamp()
: super(
priority: SpaceshipExitRail.ballPriorityWhenOnSpaceshipExitRail - 1,
priority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail - 1,
) {
renderBody = false;
layer = Layer.spaceshipExitRail;
@ -75,7 +75,7 @@ class _SpaceshipExitRailRamp extends BodyComponent
final middleLeftCurveShape = BezierCurveShape(
controlPoints: [
Vector2(-30.93, 18.2),
topLeftCurveShape.vertices.last,
Vector2(-22.6, 10.3),
Vector2(-30, 0.2),
],
@ -85,7 +85,7 @@ class _SpaceshipExitRailRamp extends BodyComponent
final bottomLeftCurveShape = BezierCurveShape(
controlPoints: [
Vector2(-30, 0.2),
middleLeftCurveShape.vertices.last,
Vector2(-36, -8.6),
Vector2(-32.04, -18.3),
],
@ -103,7 +103,7 @@ class _SpaceshipExitRailRamp extends BodyComponent
final middleRightCurveShape = BezierCurveShape(
controlPoints: [
Vector2(-27.2, 21.3),
topRightStraightShape.vertex1,
Vector2(-16.5, 11.4),
Vector2(-25.29, -1.7),
],
@ -113,7 +113,7 @@ class _SpaceshipExitRailRamp extends BodyComponent
final bottomRightCurveShape = BezierCurveShape(
controlPoints: [
Vector2(-25.29, -1.7),
middleRightCurveShape.vertices.last,
Vector2(-29.91, -8.5),
Vector2(-26.8, -15.7),
],
@ -144,7 +144,7 @@ class _SpaceshipExitRailRamp extends BodyComponent
Future<void> _loadSprite() async {
final sprite = await gameRef.loadSprite(
Assets.images.components.spaceshipDropTube.path,
Assets.images.spaceshipRamp.spaceshipDropTube.keyName,
);
final spriteComponent = SpriteComponent(
sprite: sprite,
@ -157,13 +157,13 @@ class _SpaceshipExitRailRamp extends BodyComponent
}
}
class _SpaceshipExitRailForeground extends SpriteComponent with HasGameRef {
_SpaceshipExitRailForeground()
class _SpaceshipRailForeground extends SpriteComponent with HasGameRef {
_SpaceshipRailForeground()
: super(
size: Vector2(7.6, 5.7),
anchor: Anchor.center,
position: Vector2(-28.5, 19.7),
priority: SpaceshipExitRail.ballPriorityWhenOnSpaceshipExitRail + 1,
priority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail + 1,
);
@override
@ -176,11 +176,11 @@ class _SpaceshipExitRailForeground extends SpriteComponent with HasGameRef {
}
}
class _SpaceshipExitRailBase extends BodyComponent
with InitialPosition, Layered {
_SpaceshipExitRailBase({required this.radius})
/// Represents the ground bases of the [_SpaceshipRailRamp].
class _SpaceshipRailBase extends BodyComponent with InitialPosition, Layered {
_SpaceshipRailBase({required this.radius})
: super(
priority: SpaceshipExitRail.ballPriorityWhenOnSpaceshipExitRail + 1,
priority: SpaceshipRail.ballPriorityWhenOnSpaceshipRail + 1,
) {
renderBody = false;
layer = Layer.board;
@ -202,13 +202,13 @@ class _SpaceshipExitRailBase extends BodyComponent
}
}
/// {@template spaceship_exit_rail_end}
/// {@template spaceship_rail_exit}
/// A sensor [BodyComponent] responsible for sending the [Ball]
/// back to the board.
/// {@endtemplate}
class SpaceshipExitRailEnd extends RampOpening {
/// {@macro spaceship_exit_rail_end}
SpaceshipExitRailEnd()
class SpaceshipRailExit extends RampOpening {
/// {@macro spaceship_rail_exit}
SpaceshipRailExit()
: super(
insideLayer: Layer.spaceshipExitRail,
orientation: RampOrientation.down,
@ -230,14 +230,14 @@ class SpaceshipExitRailEnd extends RampOpening {
}
/// [ContactCallback] that handles the contact between the [Ball]
/// and a [SpaceshipExitRailEnd].
/// and a [SpaceshipRailExit].
///
/// It resets the [Ball] priority and filter data so it will "be back" on the
/// board.
class SpaceshipExitRailEndBallContactCallback
extends ContactCallback<SpaceshipExitRailEnd, Ball> {
class SpaceshipRailExitBallContactCallback
extends ContactCallback<SpaceshipRailExit, Ball> {
@override
void begin(SpaceshipExitRailEnd exitRail, Ball ball, _) {
void begin(SpaceshipRailExit exitRail, Ball ball, _) {
ball
..sendTo(exitRail.outsidePriority)
..layer = exitRail.outsideLayer;

@ -1,63 +1,66 @@
// ignore_for_file: public_member_api_docs, avoid_renaming_method_parameters
// ignore_for_file: avoid_renaming_method_parameters, comment_references
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/gen/assets.gen.dart';
import 'package:pinball_components/gen/assets.gen.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets;
/// A [Blueprint] which creates the [JetpackRamp].
class Jetpack extends Forge2DBlueprint {
/// {@macro spaceship}
Jetpack();
/// {@template spaceship_ramp}
/// A [Blueprint] which creates the [_SpaceshipRampBackground].
/// {@endtemplate}
class SpaceshipRamp extends Forge2DBlueprint {
/// {@macro spaceship_ramp}
SpaceshipRamp();
/// Base priority for wall while be in the ramp.
static const int ballPriorityInsideRamp = 4;
@override
void build(_) {
addAllContactCallback([
RampOpeningBallContactCallback<_JetpackRampOpening>(),
RampOpeningBallContactCallback<_SpaceshipRampOpening>(),
]);
final rightOpening = _JetpackRampOpening(
final rightOpening = _SpaceshipRampOpening(
// TODO(ruimiguel): set Board priority when defined.
outsidePriority: 1,
rotation: math.pi,
)
..initialPosition = Vector2(1.7, 19)
..layer = Layer.opening;
final leftOpening = _JetpackRampOpening(
final leftOpening = _SpaceshipRampOpening(
outsideLayer: Layer.spaceship,
outsidePriority: Spaceship.ballPriorityWhenOnSpaceship,
rotation: math.pi,
)
..initialPosition = Vector2(-13.7, 19)
..layer = Layer.jetpack;
..layer = Layer.spaceshipEntranceRamp;
final jetpackRamp = JetpackRamp();
final spaceshipRamp = _SpaceshipRampBackground();
final jetpackRampWallFg = _JetpackRampForegroundRailing();
final spaceshipRampForegroundRailing = _SpaceshipRampForegroundRailing();
final baseRight = _JetpackBase()..initialPosition = Vector2(1.7, 20);
final baseRight = _SpaceshipRampBase()..initialPosition = Vector2(1.7, 20);
addAll([
rightOpening,
leftOpening,
baseRight,
jetpackRamp,
jetpackRampWallFg,
spaceshipRamp,
spaceshipRampForegroundRailing,
]);
}
}
/// {@template jetpack_ramp}
/// Represents the upper left blue ramp of the [Board].
/// {@endtemplate}
class JetpackRamp extends BodyComponent with InitialPosition, Layered {
JetpackRamp() : super(priority: Jetpack.ballPriorityInsideRamp - 1) {
layer = Layer.jetpack;
/// Represents the upper left blue ramp of the [Board] with its background
/// railing.
class _SpaceshipRampBackground extends BodyComponent
with InitialPosition, Layered {
_SpaceshipRampBackground()
: super(priority: SpaceshipRamp.ballPriorityInsideRamp - 1) {
layer = Layer.spaceshipEntranceRamp;
}
/// Width between walls of the ramp.
@ -113,7 +116,7 @@ class JetpackRamp extends BodyComponent with InitialPosition, Layered {
Future<void> _loadSprites() async {
final spriteRamp = await gameRef.loadSprite(
Assets.images.components.spaceshipRamp.path,
Assets.images.spaceshipRamp.spaceshipRamp.keyName,
);
final spriteRampComponent = SpriteComponent(
@ -124,7 +127,7 @@ class JetpackRamp extends BodyComponent with InitialPosition, Layered {
);
final spriteRailingBg = await gameRef.loadSprite(
Assets.images.components.spaceshipRailingBg.path,
Assets.images.spaceshipRamp.spaceshipRailingBg.keyName,
);
final spriteRailingBgComponent = SpriteComponent(
sprite: spriteRailingBg,
@ -140,11 +143,12 @@ class JetpackRamp extends BodyComponent with InitialPosition, Layered {
}
}
class _JetpackRampForegroundRailing extends BodyComponent
/// Represents the foreground of the railing upper left blue ramp.
class _SpaceshipRampForegroundRailing extends BodyComponent
with InitialPosition, Layered {
_JetpackRampForegroundRailing()
: super(priority: Jetpack.ballPriorityInsideRamp + 1) {
layer = Layer.jetpack;
_SpaceshipRampForegroundRailing()
: super(priority: SpaceshipRamp.ballPriorityInsideRamp + 1) {
layer = Layer.spaceshipEntranceRamp;
}
List<FixtureDef> _createFixtureDefs() {
@ -197,7 +201,7 @@ class _JetpackRampForegroundRailing extends BodyComponent
Future<void> _loadSprites() async {
final spriteRailingFg = await gameRef.loadSprite(
Assets.images.components.spaceshipRailingFg.path,
Assets.images.spaceshipRamp.spaceshipRailingFg.keyName,
);
final spriteRailingFgComponent = SpriteComponent(
sprite: spriteRailingFg,
@ -210,8 +214,9 @@ class _JetpackRampForegroundRailing extends BodyComponent
}
}
class _JetpackBase extends BodyComponent with InitialPosition, Layered {
_JetpackBase() {
/// Represents the ground right base of the [SpaceshipRamp].
class _SpaceshipRampBase extends BodyComponent with InitialPosition, Layered {
_SpaceshipRampBase() {
layer = Layer.board;
}
@ -240,28 +245,28 @@ class _JetpackBase extends BodyComponent with InitialPosition, Layered {
}
}
/// {@template jetpack_ramp_opening}
/// [RampOpening] with [Layer.jetpack] to filter [Ball] collisions
/// inside [JetpackRamp].
/// {@template spaceship_ramp_opening}
/// [RampOpening] with [Layer.spaceshipEntranceRamp] to filter [Ball] collisions
/// inside [_SpaceshipRampBackground].
/// {@endtemplate}
class _JetpackRampOpening extends RampOpening {
/// {@macro jetpack_ramp_opening}
_JetpackRampOpening({
class _SpaceshipRampOpening extends RampOpening {
/// {@macro spaceship_ramp_opening}
_SpaceshipRampOpening({
Layer? outsideLayer,
int? outsidePriority,
required double rotation,
}) : _rotation = rotation,
super(
insideLayer: Layer.jetpack,
insideLayer: Layer.spaceshipEntranceRamp,
outsideLayer: outsideLayer,
orientation: RampOrientation.down,
insidePriority: Jetpack.ballPriorityInsideRamp,
insidePriority: SpaceshipRamp.ballPriorityInsideRamp,
outsidePriority: outsidePriority,
);
final double _rotation;
static final Vector2 _size = Vector2(JetpackRamp.width / 4, .1);
static final Vector2 _size = Vector2(_SpaceshipRampBackground.width / 4, .1);
@override
Shape get shape {

@ -29,9 +29,12 @@ flutter:
- assets/images/baseboard/
- assets/images/dino/
- assets/images/flipper/
- assets/images/launch_ramp/
- assets/images/dash_bumper/a/
- assets/images/dash_bumper/b/
- assets/images/dash_bumper/main/
- assets/images/spaceship_ramp/
- assets/images/chrome_dino/
flutter_gen:
line_length: 80

@ -35,7 +35,7 @@ class BigSquare extends BodyComponent with InitialPosition, Layered {
paint = Paint()
..color = const Color.fromARGB(255, 8, 218, 241)
..style = PaintingStyle.stroke;
layer = Layer.jetpack;
layer = Layer.spaceshipEntranceRamp;
}
@override

@ -25,7 +25,7 @@ class BasicSpaceship extends BasicGame with TapDetector {
add(
Ball(baseColor: Colors.blue)
..initialPosition = info.eventPosition.game
..layer = Layer.jetpack,
..layer = Layer.spaceshipEntranceRamp,
);
}
}

@ -17,6 +17,8 @@ class MockSpaceshipEntrance extends Mock implements SpaceshipEntrance {}
class MockSpaceshipHole extends Mock implements SpaceshipHole {}
class MockSpaceshipRailExit extends Mock implements SpaceshipRailExit {}
class MockContact extends Mock implements Contact {}
class MockContactCallback extends Mock

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

@ -0,0 +1,31 @@
// 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_components/pinball_components.dart';
import '../../helpers/helpers.dart';
void main() {
group('LaunchRamp', () {
final tester = FlameTester(TestGame.new);
tester.testGameWidget(
'renders correctly',
setUp: (game, tester) async {
await game.addFromBlueprint(LaunchRamp());
await game.ready();
game.camera.followVector2(Vector2.zero());
game.camera.zoom = 4.1;
},
// TODO(allisonryan0002): enable test when workflows are fixed.
// verify: (game, tester) async {
// await expectLater(
// find.byGame<Forge2DGame>(),
// matchesGoldenFile('golden/launch-ramp.png'),
// );
// },
);
});
}

@ -46,14 +46,15 @@ void main() {
});
test('correctly sets and gets', () {
final component = TestLayeredBodyComponent()..layer = Layer.jetpack;
expect(component.layer, Layer.jetpack);
final component = TestLayeredBodyComponent()
..layer = Layer.spaceshipEntranceRamp;
expect(component.layer, Layer.spaceshipEntranceRamp);
});
flameTester.test(
'layers correctly before being loaded',
(game) async {
const expectedLayer = Layer.jetpack;
const expectedLayer = Layer.spaceshipEntranceRamp;
final component = TestLayeredBodyComponent()..layer = expectedLayer;
await game.ensureAdd(component);
// TODO(alestiago): modify once component.loaded is available.
@ -71,7 +72,8 @@ void main() {
'when multiple different sets',
(game) async {
const expectedLayer = Layer.launcher;
final component = TestLayeredBodyComponent()..layer = Layer.jetpack;
final component = TestLayeredBodyComponent()
..layer = Layer.spaceshipEntranceRamp;
expect(component.layer, isNot(equals(expectedLayer)));
component.layer = expectedLayer;
@ -90,7 +92,7 @@ void main() {
flameTester.test(
'layers correctly after being loaded',
(game) async {
const expectedLayer = Layer.jetpack;
const expectedLayer = Layer.spaceshipEntranceRamp;
final component = TestLayeredBodyComponent();
await game.ensureAdd(component);
component.layer = expectedLayer;
@ -109,7 +111,7 @@ void main() {
final component = TestLayeredBodyComponent();
await game.ensureAdd(component);
component.layer = Layer.jetpack;
component.layer = Layer.spaceshipEntranceRamp;
expect(component.layer, isNot(equals(expectedLayer)));
component.layer = expectedLayer;
@ -133,7 +135,7 @@ void main() {
flameTester.test(
'nested Layered children will keep their layer',
(game) async {
const parentLayer = Layer.jetpack;
const parentLayer = Layer.spaceshipEntranceRamp;
const childLayer = Layer.board;
final component = TestLayeredBodyComponent()..layer = parentLayer;
@ -152,7 +154,7 @@ void main() {
flameTester.test(
'nested children will keep their layer',
(game) async {
const parentLayer = Layer.jetpack;
const parentLayer = Layer.spaceshipEntranceRamp;
final component = TestLayeredBodyComponent()..layer = parentLayer;
final childComponent = TestBodyComponent();

@ -44,7 +44,7 @@ void main() {
(game) async {
final ramp = TestRampOpening(
orientation: RampOrientation.down,
pathwayLayer: Layer.jetpack,
pathwayLayer: Layer.spaceshipEntranceRamp,
);
await game.ready();
await game.ensureAdd(ramp);
@ -59,7 +59,7 @@ void main() {
(game) async {
final ramp = TestRampOpening(
orientation: RampOrientation.down,
pathwayLayer: Layer.jetpack,
pathwayLayer: Layer.spaceshipEntranceRamp,
);
await game.ensureAdd(ramp);
@ -68,7 +68,7 @@ void main() {
);
group('first fixture', () {
const pathwayLayer = Layer.jetpack;
const pathwayLayer = Layer.spaceshipEntranceRamp;
const openingLayer = Layer.opening;
flameTester.test(
@ -124,7 +124,7 @@ void main() {
final body = MockBody();
final area = TestRampOpening(
orientation: RampOrientation.down,
pathwayLayer: Layer.jetpack,
pathwayLayer: Layer.spaceshipEntranceRamp,
);
final callback = TestRampOpeningBallContactCallback();
@ -145,7 +145,7 @@ void main() {
final body = MockBody();
final area = TestRampOpening(
orientation: RampOrientation.up,
pathwayLayer: Layer.jetpack,
pathwayLayer: Layer.spaceshipEntranceRamp,
);
final callback = TestRampOpeningBallContactCallback();
@ -165,7 +165,7 @@ void main() {
final body = MockBody();
final area = TestRampOpening(
orientation: RampOrientation.down,
pathwayLayer: Layer.jetpack,
pathwayLayer: Layer.spaceshipEntranceRamp,
)..initialPosition = Vector2(0, 10);
final callback = TestRampOpeningBallContactCallback();
@ -189,7 +189,7 @@ void main() {
final body = MockBody();
final area = TestRampOpening(
orientation: RampOrientation.up,
pathwayLayer: Layer.jetpack,
pathwayLayer: Layer.spaceshipEntranceRamp,
)..initialPosition = Vector2(0, 10);
final callback = TestRampOpeningBallContactCallback();
@ -213,7 +213,7 @@ void main() {
final body = MockBody();
final area = TestRampOpening(
orientation: RampOrientation.down,
pathwayLayer: Layer.jetpack,
pathwayLayer: Layer.spaceshipEntranceRamp,
)..initialPosition = Vector2(0, 10);
final callback = TestRampOpeningBallContactCallback();

@ -0,0 +1,82 @@
// 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_components/pinball_components.dart';
import '../../helpers/helpers.dart';
void main() {
group('SpaceshipRail', () {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new);
flameTester.test(
'loads correctly',
(game) async {
final spaceshipRail = SpaceshipRail();
await game.addFromBlueprint(spaceshipRail);
await game.ready();
for (final element in spaceshipRail.components) {
expect(game.contains(element), isTrue);
}
},
);
});
// TODO(alestiago): Make ContactCallback private and use `beginContact`
// instead.
group('SpaceshipRailExitBallContactCallback', () {
late Forge2DGame game;
late SpaceshipRailExit railExit;
late Ball ball;
late Body body;
late Fixture fixture;
late Filter filterData;
setUp(() {
game = MockGame();
railExit = MockSpaceshipRailExit();
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);
});
setUp(() {
when(() => ball.priority).thenReturn(1);
when(() => railExit.outsideLayer).thenReturn(Layer.board);
when(() => railExit.outsidePriority).thenReturn(0);
});
test('changes the ball priority on contact', () {
SpaceshipRailExitBallContactCallback().begin(
railExit,
ball,
MockContact(),
);
verify(() => ball.sendTo(railExit.outsidePriority)).called(1);
});
test('changes the ball layer on contact', () {
SpaceshipRailExitBallContactCallback().begin(
railExit,
ball,
MockContact(),
);
verify(() => ball.layer = railExit.outsideLayer).called(1);
});
});
}

@ -0,0 +1,27 @@
// ignore_for_file: cascade_invocations
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
void main() {
group('SpaceshipRamp', () {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new);
flameTester.test(
'loads correctly',
(game) async {
final spaceshipEntranceRamp = SpaceshipRamp();
await game.addFromBlueprint(spaceshipEntranceRamp);
await game.ready();
for (final element in spaceshipEntranceRamp.components) {
expect(game.contains(element), isTrue);
}
},
);
});
}

@ -1,64 +0,0 @@
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);
});
// TODO(alestiago): Make ContactCallback private and use `beginContact`
// instead.
group('SpaceshipExitHoleBallContactCallback', () {
setUp(() {
when(() => ball.priority).thenReturn(1);
when(() => exitRailEnd.outsideLayer).thenReturn(Layer.board);
when(() => exitRailEnd.outsidePriority).thenReturn(0);
});
test('changes the ball priority on contact', () {
SpaceshipExitRailEndBallContactCallback().begin(
exitRailEnd,
ball,
MockContact(),
);
verify(() => ball.sendTo(exitRailEnd.outsidePriority)).called(1);
});
test('changes the ball layer on contact', () {
SpaceshipExitRailEndBallContactCallback().begin(
exitRailEnd,
ball,
MockContact(),
);
verify(() => ball.layer = exitRailEnd.outsideLayer).called(1);
});
});
});
}

@ -66,8 +66,6 @@ class MockFilter extends Mock implements Filter {}
class MockFixture extends Mock implements Fixture {}
class MockSpaceshipExitRailEnd extends Mock implements SpaceshipExitRailEnd {}
class MockComponentSet extends Mock implements ComponentSet {}
class MockDashNestBumper extends Mock implements DashNestBumper {}

Loading…
Cancel
Save