refactor: implemented ContactCallbacks2

pull/202/head
alestiago 3 years ago
parent 6d92eb3f1d
commit 26ee4f7725

@ -1,5 +1,6 @@
// ignore_for_file: avoid_renaming_method_parameters // ignore_for_file: avoid_renaming_method_parameters
import 'package:flame/collisions.dart';
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -22,8 +23,6 @@ class AlienZone extends Component with HasGameRef<PinballGame> {
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
gameRef.addContactCallback(_ControlledAlienBumperBallContactCallback());
final lowerBumper = ControlledAlienBumper.a() final lowerBumper = ControlledAlienBumper.a()
..initialPosition = Vector2(-32.52, -9.34); ..initialPosition = Vector2(-32.52, -9.34);
final upperBumper = ControlledAlienBumper.b() final upperBumper = ControlledAlienBumper.b()
@ -41,7 +40,7 @@ class AlienZone extends Component with HasGameRef<PinballGame> {
/// {@endtemplate} /// {@endtemplate}
@visibleForTesting @visibleForTesting
class ControlledAlienBumper extends AlienBumper class ControlledAlienBumper extends AlienBumper
with Controls<_AlienBumperController>, ScorePoints { with Controls<_AlienBumperController>, ScorePoints, ContactCallbacks2 {
/// {@macro controlled_alien_bumper} /// {@macro controlled_alien_bumper}
ControlledAlienBumper.a() : super.a() { ControlledAlienBumper.a() : super.a() {
controller = _AlienBumperController(this); controller = _AlienBumperController(this);
@ -55,6 +54,12 @@ class ControlledAlienBumper extends AlienBumper
@override @override
// TODO(ruimiguel): change points when get final points map. // TODO(ruimiguel): change points when get final points map.
int get points => 20; int get points => 20;
@override
void beginContact(Object other, Contact contact) {
super.beginContact(other, contact);
if (other is Ball) controller.hit();
}
} }
/// {@template alien_bumper_controller} /// {@template alien_bumper_controller}
@ -80,16 +85,3 @@ class _AlienBumperController extends ComponentController<AlienBumper>
isActivated = !isActivated; isActivated = !isActivated;
} }
} }
/// Listens when a [Ball] bounces bounces against a [AlienBumper].
class _ControlledAlienBumperBallContactCallback
extends ContactCallback<Controls<_AlienBumperController>, Ball> {
@override
void begin(
Controls<_AlienBumperController> controlledAlienBumper,
Ball _,
Contact __,
) {
controlledAlienBumper.controller.hit();
}
}

@ -1,5 +1,5 @@
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_forge2d/forge2d_game.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
@ -9,7 +9,8 @@ import 'package:pinball_theme/pinball_theme.dart';
/// {@template controlled_ball} /// {@template controlled_ball}
/// A [Ball] with a [BallController] attached. /// A [Ball] with a [BallController] attached.
/// {@endtemplate} /// {@endtemplate}
class ControlledBall extends Ball with Controls<BallController> { class ControlledBall extends Ball<PinballGame>
with Controls<BallController>, ContactCallbacks2 {
/// A [Ball] that launches from the [Plunger]. /// A [Ball] that launches from the [Plunger].
/// ///
/// When a launched [Ball] is lost, it will decrease the [GameState.balls] /// When a launched [Ball] is lost, it will decrease the [GameState.balls]
@ -39,6 +40,14 @@ class ControlledBall extends Ball with Controls<BallController> {
controller = DebugBallController(this); controller = DebugBallController(this);
priority = Ball.boardPriority; priority = Ball.boardPriority;
} }
@override
void beginContact(Object other, Contact contact) {
if (other is ScorePoints) {
gameRef.read<GameBloc>().add(Scored(points: other.points));
gameRef.audio.score();
}
}
} }
/// {@template ball_controller} /// {@template ball_controller}
@ -51,11 +60,8 @@ class BallController extends ComponentController<Ball>
/// Removes the [Ball] from a [PinballGame]. /// Removes the [Ball] from a [PinballGame].
/// ///
/// Triggered by [BottomWallBallContactCallback] when the [Ball] falls into /// Triggered when the [Ball] falls into a [BottomWall].
/// a [BottomWall]. void lost() => component.shouldRemove = true;
void lost() {
component.shouldRemove = true;
}
/// Stops the [Ball] inside of the [SparkyComputer] while the turbo charge /// Stops the [Ball] inside of the [SparkyComputer] while the turbo charge
/// sequence runs, then boosts the ball out of the computer. /// sequence runs, then boosts the ball out of the computer.

@ -18,11 +18,11 @@ class ControlledSparkyComputer extends SparkyComputer
} }
@override @override
void build(Forge2DGame _) { void build(_) {
addContactCallback(SparkyTurboChargeSensorBallContactCallback());
final sparkyTurboChargeSensor = SparkyTurboChargeSensor() final sparkyTurboChargeSensor = SparkyTurboChargeSensor()
..initialPosition = Vector2(-13, -49.8); ..initialPosition = Vector2(-13, -49.8);
add(sparkyTurboChargeSensor); add(sparkyTurboChargeSensor);
super.build(_); super.build(_);
} }
} }
@ -40,11 +40,12 @@ class SparkyComputerController
} }
/// {@template sparky_turbo_charge_sensor} /// {@template sparky_turbo_charge_sensor}
/// Small sensor body used to detect when a ball has entered the /// Small sensor body used to detect when a ball has enters the
/// [SparkyComputer] with the [SparkyTurboChargeSensorBallContactCallback]. /// [SparkyComputer].
/// {@endtemplate} /// {@endtemplate}
@visibleForTesting @visibleForTesting
class SparkyTurboChargeSensor extends BodyComponent with InitialPosition { class SparkyTurboChargeSensor extends BodyComponent
with InitialPosition, ContactCallbacks2 {
/// {@macro sparky_turbo_charge_sensor} /// {@macro sparky_turbo_charge_sensor}
SparkyTurboChargeSensor() { SparkyTurboChargeSensor() {
renderBody = false; renderBody = false;
@ -53,32 +54,18 @@ class SparkyTurboChargeSensor extends BodyComponent with InitialPosition {
@override @override
Body createBody() { Body createBody() {
final shape = CircleShape()..radius = 0.1; final shape = CircleShape()..radius = 0.1;
final fixtureDef = FixtureDef(shape)..isSensor = true; final fixtureDef = FixtureDef(shape)..isSensor = true;
final bodyDef = BodyDef() final bodyDef = BodyDef()
..position = initialPosition ..position = initialPosition
..userData = this; ..userData = this;
return world.createBody(bodyDef)..createFixture(fixtureDef); return world.createBody(bodyDef)..createFixture(fixtureDef);
} }
}
/// {@template sparky_turbo_charge_sensor_ball_contact_callback}
/// Turbo charges the [Ball] on contact with [SparkyTurboChargeSensor].
/// {@endtemplate}
@visibleForTesting
class SparkyTurboChargeSensorBallContactCallback
extends ContactCallback<SparkyTurboChargeSensor, ControlledBall> {
/// {@macro sparky_turbo_charge_sensor_ball_contact_callback}
SparkyTurboChargeSensorBallContactCallback();
@override @override
void begin( void beginContact(Object other, Contact contact) {
SparkyTurboChargeSensor sparkyTurboChargeSensor, super.beginContact(other, contact);
ControlledBall ball,
_, if (other is ControlledBall) other.controller.turboCharge();
) {
ball.controller.turboCharge();
} }
} }

@ -23,8 +23,6 @@ class FlutterForest extends Component
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
gameRef.addContactCallback(_DashNestBumperBallContactCallback());
final signPost = FlutterSignPost()..initialPosition = Vector2(8.35, -58.3); final signPost = FlutterSignPost()..initialPosition = Vector2(8.35, -58.3);
final bigNest = _BigDashNestBumper() final bigNest = _BigDashNestBumper()
@ -81,27 +79,40 @@ class _FlutterForestController extends ComponentController<FlutterForest>
// TODO(alestiago): Revisit ScorePoints logic once the FlameForge2D // TODO(alestiago): Revisit ScorePoints logic once the FlameForge2D
// ContactCallback process is enhanced. // ContactCallback process is enhanced.
class _BigDashNestBumper extends BigDashNestBumper with ScorePoints { class _BigDashNestBumper extends BigDashNestBumper
with ScorePoints, ContactCallbacks2 {
@override @override
int get points => 20; int get points => 20;
@override
void beginContact(Object other, Contact contact) {
super.beginContact(other, contact);
if (other is! Ball) return;
final parent = this.parent;
if (parent is FlutterForest) {
parent.controller.activateBumper(this);
}
}
} }
class _SmallDashNestBumper extends SmallDashNestBumper with ScorePoints { class _SmallDashNestBumper extends SmallDashNestBumper
with ScorePoints, ContactCallbacks2 {
_SmallDashNestBumper.a() : super.a(); _SmallDashNestBumper.a() : super.a();
_SmallDashNestBumper.b() : super.b(); _SmallDashNestBumper.b() : super.b();
@override @override
int get points => 20; int get points => 20;
}
class _DashNestBumperBallContactCallback
extends ContactCallback<DashNestBumper, Ball> {
@override @override
void begin(DashNestBumper dashNestBumper, _, __) { void beginContact(Object other, Contact contact) {
final parent = dashNestBumper.parent; super.beginContact(other, contact);
if (other is! Ball) return;
final parent = this.parent;
if (parent is FlutterForest) { if (parent is FlutterForest) {
parent.controller.activateBumper(dashNestBumper); parent.controller.activateBumper(this);
} }
} }
} }

@ -16,34 +16,33 @@ class GoogleWord extends Component
/// {@macro google_word} /// {@macro google_word}
GoogleWord({ GoogleWord({
required Vector2 position, required Vector2 position,
}) : _position = position { }) : super(
children: [
_GoogleLetter(0)
..initialPosition = position + Vector2(-12.92, 1.82),
_GoogleLetter(1)
..initialPosition = position + Vector2(-8.33, -0.65),
_GoogleLetter(2)
..initialPosition = position + Vector2(-2.88, -1.75),
_GoogleLetter(3)..initialPosition = position + Vector2(2.88, -1.75),
_GoogleLetter(4)..initialPosition = position + Vector2(8.33, -0.65),
_GoogleLetter(5)..initialPosition = position + Vector2(12.92, 1.82),
],
) {
controller = _GoogleWordController(this); controller = _GoogleWordController(this);
} }
}
final Vector2 _position; /// Activates a [GoogleLetter] when it contacts with a [Ball].
class _GoogleLetter extends GoogleLetter with ContactCallbacks2 {
_GoogleLetter(int index) : super(index);
@override @override
Future<void> onLoad() async { void beginContact(Object other, Contact contact) {
await super.onLoad(); super.beginContact(other, contact);
gameRef.addContactCallback(_GoogleLetterBallContactCallback());
final offsets = [
Vector2(-12.92, 1.82),
Vector2(-8.33, -0.65),
Vector2(-2.88, -1.75),
Vector2(2.88, -1.75),
Vector2(8.33, -0.65),
Vector2(12.92, 1.82),
];
final letters = <GoogleLetter>[]; final parent = this.parent;
for (var index = 0; index < offsets.length; index++) { if (parent is GoogleWord) parent.controller.activate(this);
letters.add(
GoogleLetter(index)..initialPosition = _position + offsets[index],
);
}
await addAll(letters);
} }
} }
@ -69,15 +68,3 @@ class _GoogleWordController extends ComponentController<GoogleWord>
} }
} }
} }
/// Activates a [GoogleLetter] when it contacts with a [Ball].
class _GoogleLetterBallContactCallback
extends ContactCallback<GoogleLetter, Ball> {
@override
void begin(GoogleLetter googleLetter, _, __) {
final parent = googleLetter.parent;
if (parent is GoogleWord) {
parent.controller.activate(googleLetter);
}
}
}

@ -7,7 +7,7 @@ import 'package:pinball_flame/pinball_flame.dart';
/// A [Blueprint] which creates the [Plunger], [RocketSpriteComponent] and /// A [Blueprint] which creates the [Plunger], [RocketSpriteComponent] and
/// [LaunchRamp]. /// [LaunchRamp].
/// {@endtemplate} /// {@endtemplate}
class Launcher extends Forge2DBlueprint { class Launcher extends Blueprint {
/// {@macro launcher} /// {@macro launcher}
Launcher(); Launcher();
@ -15,7 +15,8 @@ class Launcher extends Forge2DBlueprint {
late final Plunger plunger; late final Plunger plunger;
@override @override
void build(Forge2DGame gameRef) { // ignore: avoid_renaming_method_parameters
void build(_) {
plunger = ControlledPlunger(compressionDistance: 12.3) plunger = ControlledPlunger(compressionDistance: 12.3)
..initialPosition = Vector2(40.1, 38); ..initialPosition = Vector2(40.1, 38);

@ -1,7 +1,4 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
/// {@template score_points} /// {@template score_points}
@ -17,24 +14,3 @@ mixin ScorePoints<T extends Forge2DGame> on BodyComponent<T> {
body.userData = this; body.userData = this;
} }
} }
/// {@template ball_score_points_callbacks}
/// Adds points to the score when a [Ball] collides with a [BodyComponent] that
/// implements [ScorePoints].
/// {@endtemplate}
class BallScorePointsCallback extends ContactCallback<Ball, ScorePoints> {
/// {@macro ball_score_points_callbacks}
BallScorePointsCallback(PinballGame game) : _gameRef = game;
final PinballGame _gameRef;
@override
void begin(
Ball _,
ScorePoints scorePoints,
Contact __,
) {
_gameRef.read<GameBloc>().add(Scored(points: scorePoints.points));
_gameRef.audio.score();
}
}

@ -22,8 +22,6 @@ class SparkyFireZone extends Component with HasGameRef<PinballGame> {
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
gameRef.addContactCallback(_ControlledSparkyBumperBallContactCallback());
final lowerLeftBumper = ControlledSparkyBumper.a() final lowerLeftBumper = ControlledSparkyBumper.a()
..initialPosition = Vector2(-23.15, -41.65); ..initialPosition = Vector2(-23.15, -41.65);
final upperLeftBumper = ControlledSparkyBumper.b() final upperLeftBumper = ControlledSparkyBumper.b()
@ -44,7 +42,7 @@ class SparkyFireZone extends Component with HasGameRef<PinballGame> {
/// {@endtemplate} /// {@endtemplate}
@visibleForTesting @visibleForTesting
class ControlledSparkyBumper extends SparkyBumper class ControlledSparkyBumper extends SparkyBumper
with Controls<_SparkyBumperController>, ScorePoints { with Controls<_SparkyBumperController>, ScorePoints, ContactCallbacks2 {
///{@macro controlled_sparky_bumper} ///{@macro controlled_sparky_bumper}
ControlledSparkyBumper.a() : super.a() { ControlledSparkyBumper.a() : super.a() {
controller = _SparkyBumperController(this); controller = _SparkyBumperController(this);
@ -62,6 +60,12 @@ class ControlledSparkyBumper extends SparkyBumper
@override @override
int get points => 20; int get points => 20;
@override
void beginContact(Object other, Contact contact) {
super.beginContact(other, contact);
if (other is Ball) controller.hit();
}
} }
/// {@template sparky_bumper_controller} /// {@template sparky_bumper_controller}
@ -88,16 +92,3 @@ class _SparkyBumperController extends ComponentController<SparkyBumper>
isActivated = !isActivated; isActivated = !isActivated;
} }
} }
/// Listens when a [Ball] bounces bounces against a [SparkyBumper].
class _ControlledSparkyBumperBallContactCallback
extends ContactCallback<Controls<_SparkyBumperController>, Ball> {
@override
void begin(
Controls<_SparkyBumperController> controlledSparkyBumper,
Ball _,
Contact __,
) {
controlledSparkyBumper.controller.hit();
}
}

@ -4,6 +4,7 @@ import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets; import 'package:pinball_components/pinball_components.dart' hide Assets;
import 'package:pinball_flame/pinball_flame.dart';
/// {@template wall} /// {@template wall}
/// A continuous generic and [BodyType.static] barrier that divides a game area. /// A continuous generic and [BodyType.static] barrier that divides a game area.
@ -57,26 +58,18 @@ List<Wall> createBoundaries(Forge2DGame game) {
/// {@template bottom_wall} /// {@template bottom_wall}
/// [Wall] located at the bottom of the board. /// [Wall] located at the bottom of the board.
///
/// Collisions with [BottomWall] are listened by
/// [BottomWallBallContactCallback].
/// {@endtemplate} /// {@endtemplate}
class BottomWall extends Wall { class BottomWall extends Wall with ContactCallbacks2 {
/// {@macro bottom_wall} /// {@macro bottom_wall}
BottomWall() BottomWall()
: super( : super(
start: BoardDimensions.bounds.bottomLeft.toVector2(), start: BoardDimensions.bounds.bottomLeft.toVector2(),
end: BoardDimensions.bounds.bottomRight.toVector2(), end: BoardDimensions.bounds.bottomRight.toVector2(),
); );
}
/// {@template bottom_wall_ball_contact_callback}
/// Listens when a [ControlledBall] falls into a [BottomWall].
/// {@endtemplate}
class BottomWallBallContactCallback
extends ContactCallback<ControlledBall, BottomWall> {
@override @override
void begin(ControlledBall ball, BottomWall wall, Contact contact) { void beginContact(Object other, Contact contact) {
ball.controller.lost(); super.beginContact(other, contact);
if (other is ControlledBall) other.controller.lost();
} }
} }

@ -36,8 +36,6 @@ class PinballGame extends Forge2DGame
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
_addContactCallbacks();
unawaited(add(ScoreEffectController(this))); unawaited(add(ScoreEffectController(this)));
unawaited(add(gameFlowController = GameFlowController(this))); unawaited(add(gameFlowController = GameFlowController(this)));
unawaited(add(CameraController(this))); unawaited(add(CameraController(this)));
@ -69,11 +67,6 @@ class PinballGame extends Forge2DGame
await super.onLoad(); await super.onLoad();
} }
void _addContactCallbacks() {
addContactCallback(BallScorePointsCallback(this));
addContactCallback(BottomWallBallContactCallback());
}
Future<void> _addGameBoundaries() async { Future<void> _addGameBoundaries() async {
await add(BottomWall()); await add(BottomWall());
createBoundaries(this).forEach(add); createBoundaries(this).forEach(add);

@ -8,7 +8,7 @@ import 'package:pinball_flame/pinball_flame.dart';
/// {@template boundaries} /// {@template boundaries}
/// A [Blueprint] which creates the [_BottomBoundary] and [_OuterBoundary]. /// A [Blueprint] which creates the [_BottomBoundary] and [_OuterBoundary].
///{@endtemplate boundaries} ///{@endtemplate boundaries}
class Boundaries extends Forge2DBlueprint { class Boundaries extends Blueprint {
@override @override
void build(_) { void build(_) {
final bottomBoundary = _BottomBoundary(); final bottomBoundary = _BottomBoundary();

@ -11,7 +11,7 @@ import 'package:pinball_flame/pinball_flame.dart';
/// {@template dinowalls} /// {@template dinowalls}
/// A [Blueprint] which creates walls for the [ChromeDino]. /// A [Blueprint] which creates walls for the [ChromeDino].
/// {@endtemplate} /// {@endtemplate}
class DinoWalls extends Forge2DBlueprint { class DinoWalls extends Blueprint {
/// {@macro dinowalls} /// {@macro dinowalls}
DinoWalls(); DinoWalls();

@ -11,13 +11,9 @@ import 'package:pinball_flame/pinball_flame.dart';
/// A [Blueprint] which creates the [_LaunchRampBase] and /// A [Blueprint] which creates the [_LaunchRampBase] and
/// [_LaunchRampForegroundRailing]. /// [_LaunchRampForegroundRailing].
/// {@endtemplate} /// {@endtemplate}
class LaunchRamp extends Forge2DBlueprint { class LaunchRamp extends Blueprint {
@override @override
void build(_) { void build(_) {
addAllContactCallback([
LayerSensorBallContactCallback<_LaunchRampExit>(),
]);
final launchRampBase = _LaunchRampBase(); final launchRampBase = _LaunchRampBase();
final launchRampForegroundRailing = _LaunchRampForegroundRailing(); final launchRampForegroundRailing = _LaunchRampForegroundRailing();

@ -2,6 +2,7 @@
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
/// {@template layer_entrance_orientation} /// {@template layer_entrance_orientation}
/// Determines if a layer entrance is oriented [up] or [down] on the board. /// Determines if a layer entrance is oriented [up] or [down] on the board.
@ -23,7 +24,8 @@ enum LayerEntranceOrientation {
/// By default the base [layer] is set to [Layer.board] and the /// By default the base [layer] is set to [Layer.board] and the
/// [outsidePriority] is set to the lowest possible [Layer]. /// [outsidePriority] is set to the lowest possible [Layer].
/// {@endtemplate} /// {@endtemplate}
abstract class LayerSensor extends BodyComponent with InitialPosition, Layered { abstract class LayerSensor extends BodyComponent
with InitialPosition, Layered, ContactCallbacks2 {
/// {@macro layer_sensor} /// {@macro layer_sensor}
LayerSensor({ LayerSensor({
required Layer insideLayer, required Layer insideLayer,
@ -75,35 +77,30 @@ abstract class LayerSensor extends BodyComponent with InitialPosition, Layered {
return world.createBody(bodyDef)..createFixture(fixtureDef); return world.createBody(bodyDef)..createFixture(fixtureDef);
} }
}
/// {@template layer_sensor_ball_contact_callback}
/// Detects when a [Ball] enters or exits a [Layer] through a [LayerSensor].
///
/// Modifies [Ball]'s [Layer] and render priority depending on whether the
/// [Ball] is on or outside of a [Layer].
/// {@endtemplate}
class LayerSensorBallContactCallback<LayerEntrance extends LayerSensor>
extends ContactCallback<Ball, LayerEntrance> {
@override @override
void begin(Ball ball, LayerEntrance layerEntrance, Contact _) { void beginContact(Object other, Contact contact) {
if (ball.layer != layerEntrance.insideLayer) { super.beginContact(other, contact);
if (other is! Ball) return;
final ball = other;
if (ball.layer != insideLayer) {
final isBallEnteringOpening = final isBallEnteringOpening =
(layerEntrance.orientation == LayerEntranceOrientation.down && (orientation == LayerEntranceOrientation.down &&
ball.body.linearVelocity.y < 0) || ball.body.linearVelocity.y < 0) ||
(layerEntrance.orientation == LayerEntranceOrientation.up && (orientation == LayerEntranceOrientation.up &&
ball.body.linearVelocity.y > 0); ball.body.linearVelocity.y > 0);
if (isBallEnteringOpening) { if (isBallEnteringOpening) {
ball ball
..layer = layerEntrance.insideLayer ..layer = insideLayer
..priority = layerEntrance.insidePriority ..priority = insidePriority
..reorderChildren(); ..reorderChildren();
} }
} else { } else {
ball ball
..layer = layerEntrance.outsideLayer ..layer = outsideLayer
..priority = layerEntrance.outsidePriority ..priority = outsidePriority
..reorderChildren(); ..reorderChildren();
} }
} }

@ -9,7 +9,7 @@ import 'package:pinball_flame/pinball_flame.dart';
/// A [Blueprint] which creates the pair of [Slingshot]s on the right side of /// A [Blueprint] which creates the pair of [Slingshot]s on the right side of
/// the board. /// the board.
/// {@endtemplate} /// {@endtemplate}
class Slingshots extends Forge2DBlueprint { class Slingshots extends Blueprint {
@override @override
void build(_) { void build(_) {
final upperSlingshot = Slingshot( final upperSlingshot = Slingshot(

@ -12,7 +12,7 @@ import 'package:pinball_flame/pinball_flame.dart';
/// {@template spaceship} /// {@template spaceship}
/// A [Blueprint] which creates the spaceship feature. /// A [Blueprint] which creates the spaceship feature.
/// {@endtemplate} /// {@endtemplate}
class Spaceship extends Forge2DBlueprint { class Spaceship extends Blueprint {
/// {@macro spaceship} /// {@macro spaceship}
Spaceship({required this.position}); Spaceship({required this.position});
@ -24,11 +24,6 @@ class Spaceship extends Forge2DBlueprint {
@override @override
void build(_) { void build(_) {
addAllContactCallback([
LayerSensorBallContactCallback<_SpaceshipEntrance>(),
LayerSensorBallContactCallback<_SpaceshipHole>(),
]);
addAll([ addAll([
SpaceshipSaucer()..initialPosition = position, SpaceshipSaucer()..initialPosition = position,
_SpaceshipEntrance()..initialPosition = position, _SpaceshipEntrance()..initialPosition = position,

@ -11,16 +11,12 @@ import 'package:pinball_flame/pinball_flame.dart';
/// {@template spaceship_rail} /// {@template spaceship_rail}
/// A [Blueprint] for the spaceship drop tube. /// A [Blueprint] for the spaceship drop tube.
/// {@endtemplate} /// {@endtemplate}
class SpaceshipRail extends Forge2DBlueprint { class SpaceshipRail extends Blueprint {
/// {@macro spaceship_rail} /// {@macro spaceship_rail}
SpaceshipRail(); SpaceshipRail();
@override @override
void build(_) { void build(_) {
addAllContactCallback([
LayerSensorBallContactCallback<_SpaceshipRailExit>(),
]);
final railRamp = _SpaceshipRailRamp(); final railRamp = _SpaceshipRailRamp();
final railEnd = _SpaceshipRailExit(); final railEnd = _SpaceshipRailExit();
final topBase = _SpaceshipRailBase(radius: 0.55) final topBase = _SpaceshipRailBase(radius: 0.55)

@ -11,16 +11,12 @@ import 'package:pinball_flame/pinball_flame.dart';
/// {@template spaceship_ramp} /// {@template spaceship_ramp}
/// A [Blueprint] which creates the ramp leading into the [Spaceship]. /// A [Blueprint] which creates the ramp leading into the [Spaceship].
/// {@endtemplate} /// {@endtemplate}
class SpaceshipRamp extends Forge2DBlueprint { class SpaceshipRamp extends Blueprint {
/// {@macro spaceship_ramp} /// {@macro spaceship_ramp}
SpaceshipRamp(); SpaceshipRamp();
@override @override
void build(_) { void build(_) {
addAllContactCallback([
LayerSensorBallContactCallback<_SpaceshipRampOpening>(),
]);
final rightOpening = _SpaceshipRampOpening( final rightOpening = _SpaceshipRampOpening(
// TODO(ruimiguel): set Board priority when defined. // TODO(ruimiguel): set Board priority when defined.
outsidePriority: 1, outsidePriority: 1,

@ -9,7 +9,7 @@ import 'package:pinball_flame/pinball_flame.dart';
/// A [Blueprint] which creates the [_ComputerBase] and /// A [Blueprint] which creates the [_ComputerBase] and
/// [_ComputerTopSpriteComponent]. /// [_ComputerTopSpriteComponent].
/// {@endtemplate} /// {@endtemplate}
class SparkyComputer extends Forge2DBlueprint { class SparkyComputer extends Blueprint {
@override @override
void build(_) { void build(_) {
final computerBase = _ComputerBase(); final computerBase = _ComputerBase();

@ -17,7 +17,7 @@ class GoogleLetterGame extends BasicBallGame {
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
addContactCallback(_BallGoogleLetterContactCallback()); world.setContactListener(_WorldContactListener());
camera.followVector2(Vector2.zero()); camera.followVector2(Vector2.zero());
await add(GoogleLetter(0)); await add(GoogleLetter(0));
@ -26,11 +26,21 @@ class GoogleLetterGame extends BasicBallGame {
} }
} }
class _BallGoogleLetterContactCallback class _WorldContactListener extends ContactListener {
extends ContactCallback<Ball, GoogleLetter> {
@override @override
void begin(Ball<Forge2DGame> a, GoogleLetter b, Contact contact) { void beginContact(Contact contact) {
super.begin(a, b, contact); [
b.activate(); contact.bodyA.userData,
contact.bodyB.userData,
].whereType<GoogleLetter>().first.activate();
} }
@override
void endContact(Contact contact) {}
@override
void postSolve(Contact contact, ContactImpulse impulse) {}
@override
void preSolve(Contact contact, Manifold oldManifold) {}
} }

@ -61,36 +61,6 @@ abstract class Blueprint<T extends FlameGame> extends Component {
List<Blueprint> get blueprints => List.unmodifiable(_blueprints); List<Blueprint> get blueprints => List.unmodifiable(_blueprints);
} }
/// A [Blueprint] that provides additional
/// structures specific to flame_forge2d
abstract class Forge2DBlueprint extends Blueprint<Forge2DGame> {
final List<ContactCallback> _callbacks = [];
/// Adds a single [ContactCallback] to this blueprint
void addContactCallback(ContactCallback callback) {
assert(!_isAttached, _attachedErrorMessage);
_callbacks.add(callback);
}
/// Adds a collection of [ContactCallback]s to this blueprint
void addAllContactCallback(List<ContactCallback> callbacks) {
assert(!_isAttached, _attachedErrorMessage);
_callbacks.addAll(callbacks);
}
@override
Future<void> attach(Forge2DGame game) async {
await super.attach(game);
for (final callback in _callbacks) {
game.addContactCallback(callback);
}
}
/// Returns a copy of the callbacks built by this blueprint
List<ContactCallback> get callbacks => List.unmodifiable(_callbacks);
}
/// Adds helper methods regardin [Blueprint]s to [FlameGame] /// Adds helper methods regardin [Blueprint]s to [FlameGame]
extension FlameGameBlueprint on FlameGame { extension FlameGameBlueprint on FlameGame {
/// Shortcut to attach a [Blueprint] instance to this game /// Shortcut to attach a [Blueprint] instance to this game

Loading…
Cancel
Save