refactor: splitted layer from rampopening

pull/40/head
RuiAlonso 4 years ago
parent 965c14be60
commit 0c240f12de

@ -11,6 +11,7 @@ export 'launcher_ramp.dart';
export 'layer.dart'; export 'layer.dart';
export 'pathway.dart'; export 'pathway.dart';
export 'plunger.dart'; export 'plunger.dart';
export 'ramp_opening.dart';
export 'round_bumper.dart'; export 'round_bumper.dart';
export 'score_points.dart'; export 'score_points.dart';
export 'sling_shot.dart'; export 'sling_shot.dart';

@ -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';
/// Modifies maskBits of [BodyComponent] to control what other bodies it can /// Modifies maskBits of [BodyComponent] to control what other bodies it can
/// have physical interactions with. /// have physical interactions with.
@ -70,97 +67,3 @@ extension LayerX on Layer {
} }
} }
} }
/// Indicates the orientation of a ramp entrance/exit.
///
/// Used to know if a ramp is facing up or down on the board.
enum RampOrientation {
/// Facing up on the board.
up,
/// Facing down on the board.
down,
}
/// {@template ramp_opening}
/// [BodyComponent] located at the entrance and exit of a ramp.
///
/// [RampOpeningBallContactCallback] detects when a [Ball] passes
/// through this opening. By default openings are [Layer.board] that
/// means opening are at ground level, not over board.
/// {@endtemplate}
abstract class RampOpening extends BodyComponent with InitialPosition {
/// {@macro ramp_opening}
RampOpening({
required Layer pathwayLayer,
Layer? openingLayer,
}) : _pathwayLayer = pathwayLayer,
_openingLayer = openingLayer ?? Layer.board;
final Layer _openingLayer;
final Layer _pathwayLayer;
/// Mask of category bits for collision with [RampOpening].
Layer get openingLayer => _openingLayer;
/// Mask of category bits for collision inside [Pathway].
Layer get pathwayLayer => _pathwayLayer;
/// The [Shape] of the [RampOpening].
Shape get shape;
/// Orientation of the [RampOpening] entrance/exit
// TODO(ruimiguel): Try to remove the need of [RampOrientation] for collision
// calculations.
RampOrientation get orientation;
@override
Body createBody() {
final fixtureDef = FixtureDef(shape)
..isSensor = true
..filter.categoryBits = _openingLayer.maskBits;
final bodyDef = BodyDef()
..userData = this
..position = initialPosition
..type = BodyType.static;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
/// {@template ramp_opening_ball_contact_callback}
/// Detects when a [Ball] enters or exits a [Pathway] ramp through a
/// [RampOpening].
///
/// Modifies [Ball]'s maskBits while it is inside the ramp. When [Ball] exits,
/// sets maskBits to collide with all elements.
/// {@endtemplate}
class RampOpeningBallContactCallback<Opening extends RampOpening>
extends ContactCallback<Ball, Opening> {
/// Collection of balls inside ramp pathway.
final _ballsInside = <Ball>{};
@override
void begin(Ball ball, Opening opening, Contact _) {
late final Layer layer;
if (!_ballsInside.contains(ball)) {
layer = opening.pathwayLayer;
_ballsInside.add(ball);
} else {
layer = Layer.board;
_ballsInside.remove(ball);
}
ball.layer = layer;
}
@override
void end(Ball ball, Opening opening, Contact _) {
final isBallOutsideOpening = opening.orientation == RampOrientation.up
? ball.body.position.y > opening.body.position.y
: ball.body.position.y < opening.body.position.y;
if (isBallOutsideOpening) ball.layer = Layer.board;
}
}

@ -0,0 +1,98 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
/// Indicates the orientation of a ramp entrance/exit.
///
/// Used to know if a ramp is facing up or down on the board.
enum RampOrientation {
/// Facing up on the board.
up,
/// Facing down on the board.
down,
}
/// {@template ramp_opening}
/// [BodyComponent] located at the entrance and exit of a ramp.
///
/// [RampOpeningBallContactCallback] detects when a [Ball] passes
/// through this opening. By default openings are [Layer.board] that
/// means opening are at ground level, not over board.
/// {@endtemplate}
abstract class RampOpening extends BodyComponent with InitialPosition {
/// {@macro ramp_opening}
RampOpening({
required Layer pathwayLayer,
Layer? openingLayer,
}) : _pathwayLayer = pathwayLayer,
_openingLayer = openingLayer ?? Layer.board;
final Layer _openingLayer;
final Layer _pathwayLayer;
/// Mask of category bits for collision with [RampOpening].
Layer get openingLayer => _openingLayer;
/// Mask of category bits for collision inside [Pathway].
Layer get pathwayLayer => _pathwayLayer;
/// The [Shape] of the [RampOpening].
Shape get shape;
/// Orientation of the [RampOpening] entrance/exit
// TODO(ruimiguel): Try to remove the need of [RampOrientation] for collision
// calculations.
RampOrientation get orientation;
@override
Body createBody() {
final fixtureDef = FixtureDef(shape)
..isSensor = true
..filter.categoryBits = _openingLayer.maskBits;
final bodyDef = BodyDef()
..userData = this
..position = initialPosition
..type = BodyType.static;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
/// {@template ramp_opening_ball_contact_callback}
/// Detects when a [Ball] enters or exits a [Pathway] ramp through a
/// [RampOpening].
///
/// Modifies [Ball]'s maskBits while it is inside the ramp. When [Ball] exits,
/// sets maskBits to collide with all elements.
/// {@endtemplate}
class RampOpeningBallContactCallback<Opening extends RampOpening>
extends ContactCallback<Ball, Opening> {
/// Collection of balls inside ramp pathway.
final _ballsInside = <Ball>{};
@override
void begin(Ball ball, Opening opening, Contact _) {
late final Layer layer;
if (!_ballsInside.contains(ball)) {
layer = opening.pathwayLayer;
_ballsInside.add(ball);
} else {
layer = Layer.board;
_ballsInside.remove(ball);
}
ball.layer = layer;
}
@override
void end(Ball ball, Opening opening, Contact _) {
final isBallOutsideOpening = opening.orientation == RampOrientation.up
? ball.body.position.y > opening.body.position.y
: ball.body.position.y < opening.body.position.y;
if (isBallOutsideOpening) ball.layer = Layer.board;
}
}
Loading…
Cancel
Save