diff --git a/lib/game/components/crossing_ramp.dart b/lib/game/components/crossing_ramp.dart
index 3b9b4c53..315318f0 100644
--- a/lib/game/components/crossing_ramp.dart
+++ b/lib/game/components/crossing_ramp.dart
@@ -3,13 +3,37 @@
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
-enum RampOrientation { up, down }
+/// Indicates a orientation of the ramp entrance/exit.
+///
+/// Used to know if ramps are looking up or down of the board.
+enum RampOrientation {
+ /// Looking up of the board.
+ up,
+
+ /// Looking up of the board.
+ down,
+}
+
+/// Indicates a type of the ramp.
+///
+/// Used to set the maskBits of the ramp to determine their possible collisions.
+enum RampType {
+ /// Collide with all elements.
+ all,
-enum RampType { all, jetpack, sparky }
+ /// Collide only with Jetpack group elements.
+ jetpack,
+ /// Collide only with Sparky group elements.
+ sparky,
+}
+
+/// Utility methods for [RampType].
extension RampTypeX on RampType {
+ /// Mask of bits for each [RampType].
int get maskBits => _getRampMaskBits(this);
+ /// Mask of bits for each [RampType].
int _getRampMaskBits(RampType type) {
switch (type) {
case RampType.all:
@@ -22,17 +46,26 @@ extension RampTypeX on RampType {
}
}
+/// {@template ramp_area}
+/// [BodyComponent] located at the entrance and exit of a ramp.
+///
+/// Detects when a [Ball] goes through it,
+/// Collisions with [RampArea] are listened by [RampAreaCallback].
+/// {@endtemplate}
abstract class RampArea extends BodyComponent {
RampArea({
required Vector2 position,
- required int maskBits,
+ required int categoryBits,
}) : _position = position,
- _maskBits = maskBits;
+ _categoryBits = categoryBits {
+ // TODO(ruialonso): remove paint color for BodyComponent.
+ // Left white for dev and testing.
+ }
final Vector2 _position;
- final int _maskBits;
+ final int _categoryBits;
- int get maskBits => _maskBits;
+ int get categoryBits => _categoryBits;
Shape get shape;
RampOrientation get orientation;
@@ -46,16 +79,21 @@ abstract class RampArea extends BodyComponent {
..type = BodyType.static;
final body = world.createBody(bodyDef);
- body.createFixture(fixtureDef).filterData
- ..categoryBits = Filter().maskBits
- ..maskBits = Filter().maskBits;
+ body.createFixture(fixtureDef).filterData.categoryBits = _categoryBits;
return body;
}
}
+/// {@template ramp_area_callback}
+/// Listens when a [Ball] goes through a [RampArea] and gets into a [Pathway]
+/// ramp, in order to avoid collisions with other crossing ramps.
+/// Modifies [Ball]'s maskBits while is inside the ramp. When exits sets [Ball]
+/// maskBits to collide with all elements.
+/// {@endtemplate}
abstract class RampAreaCallback
extends ContactCallback {
+ /// Collection of balls inside ramp pathway.
Set get ballsInside;
@override
@@ -66,7 +104,7 @@ abstract class RampAreaCallback
) {
int maskBits;
if (!ballsInside.contains(ball)) {
- maskBits = area.maskBits;
+ maskBits = area.categoryBits;
ballsInside.add(ball);
} else {
maskBits = RampType.all.maskBits;
diff --git a/lib/game/components/jetpack_ramp.dart b/lib/game/components/jetpack_ramp.dart
index d5b805f8..78102f8e 100644
--- a/lib/game/components/jetpack_ramp.dart
+++ b/lib/game/components/jetpack_ramp.dart
@@ -3,12 +3,25 @@ import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
+/// {@template jetpack_ramp}
+/// Represent the upper left blue ramp for the game.
+///
+/// Group of [Component]s composed by a [Pathway.arc] as the ramp, and two
+/// [JetpackRampArea] at the entrance and exit of the ramp, to detect when
+/// a ball gets into/out of the ramp.
+/// {@endtemplate}
class JetpackRamp extends PositionComponent with HasGameRef {
JetpackRamp({
required Vector2 position,
}) : _position = position,
super();
+ final double _radius = 200;
+ final double _width = 80;
+ final double _angle = radians(210);
+ final double _rotation = radians(-10);
+ final double _entranceRotation = radians(15);
+ final double _exitRotation = radians(-5);
final Vector2 _position;
@override
@@ -17,25 +30,25 @@ class JetpackRamp extends PositionComponent with HasGameRef {
Pathway.arc(
color: const Color.fromARGB(255, 8, 218, 241),
position: _position,
- width: 80,
- radius: 200,
- angle: radians(210),
- rotation: radians(-10),
- maskBits: RampType.jetpack.maskBits,
+ width: _width,
+ radius: _radius,
+ angle: _angle,
+ rotation: _rotation,
+ categoryBits: RampType.jetpack.maskBits,
),
);
await add(
JetpackRampArea(
position: _position + Vector2(-10.5, 0),
- rotation: radians(15),
+ rotation: _entranceRotation,
orientation: RampOrientation.down,
),
);
await add(
JetpackRampArea(
position: _position + Vector2(20.5, 3),
- rotation: radians(-5),
+ rotation: _exitRotation,
orientation: RampOrientation.down,
),
);
@@ -44,6 +57,12 @@ class JetpackRamp extends PositionComponent with HasGameRef {
}
}
+/// {@template jetpack_ramp_area}
+/// Implementation of [RampArea] for sensors in [JetpackRamp].
+///
+/// [RampArea] with [RampType.jetpack] to filter [Ball]s collisions
+/// inside [JetpackRamp].
+/// {@endtemplate}
class JetpackRampArea extends RampArea {
JetpackRampArea({
required Vector2 position,
@@ -53,11 +72,18 @@ class JetpackRampArea extends RampArea {
_orientation = orientation,
super(
position: position,
- maskBits: RampType.jetpack.maskBits,
+ categoryBits: RampType.jetpack.maskBits,
);
+ /// Orientation of entrance/exit of [JetpackRamp] where
+ /// this [JetpackRampArea] is placed.
final RampOrientation _orientation;
+
+ /// Rotation of the [RampArea] to place it right at the
+ /// entrance/exit of [JetpackRamp].
final double _rotation;
+
+ /// Size of the [RampArea] placed at the entrance/exit of [JetpackRamp].
final int _size = 7;
@override
@@ -73,9 +99,15 @@ class JetpackRampArea extends RampArea {
]);
}
+/// {@template jetpack_ramp_area_callback}
+/// Implementation of [RampAreaCallback] to listen when a [Ball]
+/// gets into a [JetpackRampArea].
+/// {@endtemplate}
class JetpackRampAreaCallback extends RampAreaCallback {
+ /// {@macro jetpack_ramp_area_callback}
JetpackRampAreaCallback() : super();
+ /// Collection of balls inside [JetpackRamp].
final _ballsInsideJetpack = {};
@override
diff --git a/lib/game/components/pathway.dart b/lib/game/components/pathway.dart
index 7e67ee5a..8546a9ed 100644
--- a/lib/game/components/pathway.dart
+++ b/lib/game/components/pathway.dart
@@ -14,10 +14,10 @@ class Pathway extends BodyComponent {
Color? color,
required Vector2 position,
required List> paths,
- int? maskBits,
+ int? categoryBits,
}) : _position = position,
_paths = paths,
- _maskBits = maskBits ?? Filter().maskBits {
+ _categoryBits = categoryBits ?? Filter().categoryBits {
paint = Paint()
..color = color ?? const Color.fromARGB(0, 0, 0, 0)
..style = PaintingStyle.stroke;
@@ -38,7 +38,7 @@ class Pathway extends BodyComponent {
required double width,
double rotation = 0,
bool singleWall = false,
- int? maskBits,
+ int? categoryBits,
}) {
final paths = >[];
@@ -61,7 +61,7 @@ class Pathway extends BodyComponent {
color: color,
position: position,
paths: paths,
- maskBits: maskBits,
+ categoryBits: categoryBits,
);
}
@@ -87,7 +87,7 @@ class Pathway extends BodyComponent {
required double angle,
double rotation = 0,
bool singleWall = false,
- int? maskBits,
+ int? categoryBits,
}) {
final paths = >[];
@@ -114,7 +114,7 @@ class Pathway extends BodyComponent {
color: color,
position: position,
paths: paths,
- maskBits: maskBits,
+ categoryBits: categoryBits,
);
}
@@ -134,7 +134,7 @@ class Pathway extends BodyComponent {
required double width,
double rotation = 0,
bool singleWall = false,
- int? maskBits,
+ int? categoryBits,
}) {
final paths = >[];
@@ -157,13 +157,13 @@ class Pathway extends BodyComponent {
color: color,
position: position,
paths: paths,
- maskBits: maskBits,
+ categoryBits: categoryBits,
);
}
Vector2 _position;
List> _paths;
- int _maskBits;
+ int _categoryBits;
@override
Body createBody() {
@@ -179,9 +179,7 @@ class Pathway extends BodyComponent {
);
final fixtureDef = FixtureDef(chain);
- body.createFixture(fixtureDef)
- ..filterData.categoryBits = _maskBits
- ..filterData.maskBits = _maskBits;
+ body.createFixture(fixtureDef).filterData.categoryBits = _categoryBits;
}
return body;
diff --git a/lib/game/components/sparky_ramp.dart b/lib/game/components/sparky_ramp.dart
index d23f7561..5f351a83 100644
--- a/lib/game/components/sparky_ramp.dart
+++ b/lib/game/components/sparky_ramp.dart
@@ -4,12 +4,22 @@ import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
+/// {@template sparky_ramp}
+/// Represent the upper right yellow ramp for the game.
+///
+/// Group of [Component]s composed by a [Pathway.arc] as the ramp, and two
+/// [SparkyRampArea] at the entrance and exit of the ramp, to detect when
+/// a ball gets into/out of the ramp.
+/// {@endtemplate}
class SparkyRamp extends PositionComponent with HasGameRef {
SparkyRamp({
required Vector2 position,
}) : _position = position,
super();
+ final double _radius = 300;
+ final double _width = 80;
+ final double _angle = math.pi;
final Vector2 _position;
@override
@@ -18,10 +28,10 @@ class SparkyRamp extends PositionComponent with HasGameRef {
Pathway.arc(
color: const Color.fromARGB(255, 251, 255, 0),
position: _position,
- radius: 300,
- angle: math.pi,
- width: 80,
- maskBits: RampType.sparky.maskBits,
+ radius: _radius,
+ angle: _angle,
+ width: _width,
+ categoryBits: RampType.sparky.maskBits,
),
);
await add(
@@ -41,6 +51,12 @@ class SparkyRamp extends PositionComponent with HasGameRef {
}
}
+/// {@template sparky_ramp_area}
+/// Implementation of [RampArea] for sensors in [SparkyRamp].
+///
+/// [RampArea] with [RampType.sparky] to filter [Ball]s collisions
+/// inside [SparkyRamp].
+/// {@endtemplate}
class SparkyRampArea extends RampArea {
SparkyRampArea({
required Vector2 position,
@@ -50,11 +66,18 @@ class SparkyRampArea extends RampArea {
_orientation = orientation,
super(
position: position,
- maskBits: RampType.sparky.maskBits,
+ categoryBits: RampType.sparky.maskBits,
);
+ /// Orientation of entrance/exit of [SparkyRamp] where
+ /// this [SparkyRampArea] is placed.
final RampOrientation _orientation;
+
+ /// Rotation of the [RampArea] to place it right at the
+ /// entrance/exit of [SparkyRamp].
final double _rotation;
+
+ /// Size of the [RampArea] placed at the entrance/exit of [SparkyRamp].
final int _size = 7;
@override
@@ -70,9 +93,14 @@ class SparkyRampArea extends RampArea {
]);
}
+/// {@template sparky_ramp_area_callback}
+/// Implementation of [RampAreaCallback] to listen when a [Ball]
+/// gets into a [SparkyRampArea].
+/// {@endtemplate}
class SparkyRampAreaCallback extends RampAreaCallback {
SparkyRampAreaCallback() : super();
+ /// Collection of balls inside [SparkyRamp].
final _ballsInsideSparky = {};
@override