feat: allow jetpack ramp to be over the board

pull/40/head
RuiAlonso 4 years ago
parent 7c76b70bba
commit 688941b9fd

@ -12,7 +12,7 @@ class Ball extends BodyComponent<PinballGame> with Layered {
required Vector2 position,
Layer? layer,
}) : _position = position,
_layer = layer ?? Layer.all;
_layer = layer ?? Layer.board;
/// The initial position of the [Ball] body.
final Vector2 _position;

@ -19,8 +19,6 @@ class JetpackRamp extends Component with HasGameRef<PinballGame> {
final double _width = 80;
final double _angle = radians(210);
final double _rotation = radians(-10);
final double _entranceRotation = radians(15);
final double _exitRotation = radians(-5);
/// The position of this [JetpackRamp]
final Vector2 position;
@ -41,16 +39,16 @@ class JetpackRamp extends Component with HasGameRef<PinballGame> {
await add(
JetpackRampOpening(
position: position + Vector2(-10.5, 0),
rotation: _entranceRotation,
position: position + Vector2(-11, .5),
orientation: RampOrientation.down,
rotation: radians(15),
),
);
await add(
JetpackRampOpening(
position: position + Vector2(20.5, 3),
rotation: _exitRotation,
position: position + Vector2(20.5, 3.4),
orientation: RampOrientation.down,
rotation: radians(-9),
),
);
@ -66,13 +64,15 @@ class JetpackRampOpening extends RampOpening {
/// {@macro jetpack_ramp_opening}
JetpackRampOpening({
required Vector2 position,
double rotation = 0,
required RampOrientation orientation,
double rotation = 0,
Layer? openingLayer,
}) : _rotation = rotation,
_orientation = orientation,
super(
position: position,
layer: Layer.jetpack,
pathwayLayer: Layer.jetpack,
openingLayer: openingLayer,
);
/// Orientation of entrance/exit of [JetpackRamp] where

@ -33,6 +33,7 @@ class LauncherRamp extends Component with HasGameRef<PinballGame> {
start: Vector2(0, 0),
end: Vector2(0, 600),
width: 80,
layer: Layer.launcher,
),
);
@ -48,7 +49,7 @@ class LauncherRamp extends Component with HasGameRef<PinballGame> {
);
await add(
LauncherRampOpening(
position: position + Vector2(-46.5, -9),
position: position + Vector2(-46.5, -8.5),
orientation: RampOrientation.down,
rotation: radians(13),
),
@ -78,7 +79,7 @@ class LauncherRampOpening extends RampOpening {
_orientation = orientation,
super(
position: position,
layer: Layer.launcher,
pathwayLayer: Layer.launcher,
);
/// Orientation of entrance/exit of [LauncherRamp] where

@ -29,6 +29,9 @@ enum Layer {
/// Collide with all elements.
all,
/// Collide only with board elements (the ground level).
board,
/// Collide only with Jetpack group elements.
jetpack,
@ -43,6 +46,8 @@ extension LayerX on Layer {
switch (this) {
case Layer.all:
return 0xFFFF;
case Layer.board:
return 0xFF0F;
case Layer.jetpack:
return 0x0010;
case Layer.launcher:
@ -66,24 +71,31 @@ enum RampOrientation {
/// [BodyComponent] located at the entrance and exit of a ramp.
///
/// [RampOpeningBallContactCallback] detects when a [Ball] passes
/// through this opening.
/// 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 {
/// {@macro ramp_opening}
RampOpening({
required Vector2 position,
required Layer layer,
required Layer pathwayLayer,
Layer? openingLayer,
}) : _position = position,
_layer = layer {
_pathwayLayer = pathwayLayer,
_openingLayer = openingLayer ?? Layer.board {
// TODO(ruialonso): remove paint color for BodyComponent.
// Left white for dev and testing.
}
final Vector2 _position;
final Layer _layer;
final Layer _openingLayer;
final Layer _pathwayLayer;
/// Mask of category bits for collision with [RampOpening]
Layer get layer => _layer;
Layer get openingLayer => _openingLayer;
/// Mask of category bits for collision inside [Pathway]
Layer get pathwayLayer => _pathwayLayer;
/// The [Shape] of the [RampOpening]
Shape get shape;
@ -95,7 +107,7 @@ abstract class RampOpening extends BodyComponent {
Body createBody() {
final fixtureDef = FixtureDef(shape)
..isSensor = true
..filter.categoryBits = _layer.maskBits;
..filter.categoryBits = _openingLayer.maskBits;
final bodyDef = BodyDef()
..userData = this
@ -126,10 +138,12 @@ abstract class RampOpeningBallContactCallback<Opening extends RampOpening>
) {
Layer layer;
if (!ballsInside.contains(ball)) {
layer = opening.layer;
layer = opening.pathwayLayer;
print('TOUCH begin (add) layer=$layer');
ballsInside.add(ball);
} else {
layer = Layer.all;
layer = Layer.board;
print('TOUCH begin (remove) layer=$layer');
ballsInside.remove(ball);
}
@ -142,13 +156,19 @@ abstract class RampOpeningBallContactCallback<Opening extends RampOpening>
switch (opening.orientation) {
case RampOrientation.up:
print('TOUCH end up');
if (ball.body.position.y > opening._position.y) {
layer = Layer.all;
print('layer=$layer');
layer = Layer.board;
print('layer=$layer');
}
break;
case RampOrientation.down:
print('TOUCH end down');
if (ball.body.position.y < opening._position.y) {
layer = Layer.all;
print('layer=$layer');
layer = Layer.board;
print('layer=$layer');
}
break;
}

@ -13,7 +13,7 @@ class TestRampOpening extends RampOpening {
required RampOrientation orientation,
required Layer layer,
}) : _orientation = orientation,
super(position: position, layer: layer);
super(position: position, pathwayLayer: layer);
final RampOrientation _orientation;
@ -42,20 +42,24 @@ class TestRampOpeningBallContactCallback
void main() {
group('Layer', () {
test('has three values', () {
expect(Layer.values.length, equals(3));
test('has four values', () {
expect(Layer.values.length, equals(4));
});
});
group('LayerX', () {
test('all types are different', () {
expect(Layer.all.maskBits, isNot(equals(Layer.jetpack.maskBits)));
expect(Layer.all.maskBits, isNot(equals(Layer.board.maskBits)));
expect(Layer.board.maskBits, isNot(equals(Layer.jetpack.maskBits)));
expect(Layer.jetpack.maskBits, isNot(equals(Layer.launcher.maskBits)));
expect(Layer.launcher.maskBits, isNot(equals(Layer.all.maskBits)));
expect(Layer.launcher.maskBits, isNot(equals(Layer.board.maskBits)));
});
test('all type has default maskBits', () {
expect(Layer.all.maskBits, equals(0xFFFF));
test('all type has 0xFFFF maskBits', () {
expect(Layer.all.maskBits, equals(0xFF0F));
});
test('board type has 0xFF0F maskBits', () {
expect(Layer.board.maskBits, equals(0xFF0F));
});
test('jetpack type has 0x010 maskBits', () {
@ -77,7 +81,7 @@ void main() {
final ramp = TestRampOpening(
position: Vector2.zero(),
orientation: RampOrientation.down,
layer: Layer.all,
layer: Layer.board,
);
await game.ready();
await game.ensureAdd(ramp);
@ -94,7 +98,7 @@ void main() {
final ramp = TestRampOpening(
position: position,
orientation: RampOrientation.down,
layer: Layer.all,
layer: Layer.board,
);
await game.ensureAdd(ramp);
@ -109,7 +113,7 @@ void main() {
final ramp = TestRampOpening(
position: Vector2.zero(),
orientation: RampOrientation.down,
layer: Layer.all,
layer: Layer.board,
);
await game.ensureAdd(ramp);
@ -213,7 +217,7 @@ void main() {
callback.end(ball, area, MockContact());
verifyNever(() => ball.layer = Layer.all);
verifyNever(() => ball.layer = Layer.board);
});
test(
@ -240,7 +244,7 @@ void main() {
callback.end(ball, area, MockContact());
verifyNever(() => ball.layer = Layer.all);
verifyNever(() => ball.layer = Layer.board);
});
test(
@ -267,7 +271,7 @@ void main() {
callback.end(ball, area, MockContact());
verify(() => ball.layer = Layer.all);
verify(() => ball.layer = Layer.board);
});
test(
@ -289,11 +293,11 @@ void main() {
callback.begin(ball, area, MockContact());
expect(callback._ballsInside.isEmpty, isTrue);
verify(() => ball.layer = Layer.all).called(1);
verify(() => ball.layer = Layer.board).called(1);
callback.end(ball, area, MockContact());
verify(() => ball.layer = Layer.all).called(1);
verify(() => ball.layer = Layer.board).called(1);
});
test(
@ -315,11 +319,11 @@ void main() {
callback.begin(ball, area, MockContact());
expect(callback._ballsInside.isEmpty, isTrue);
verify(() => ball.layer = Layer.all).called(1);
verify(() => ball.layer = Layer.board).called(1);
callback.end(ball, area, MockContact());
verify(() => ball.layer = Layer.all).called(1);
verify(() => ball.layer = Layer.board).called(1);
});
});
}

Loading…
Cancel
Save