chore: refactor names, test and doc

pull/40/head
RuiAlonso 4 years ago
parent 274bdb28c5
commit dab5cbbe4f

@ -1,13 +1,12 @@
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
/// {@template jetpack_ramp}
/// Represents the upper left blue ramp for the game.
///
/// Composed of a [Pathway.arc] defining the ramp, and two
/// [JetpackRampOpening]s at the entrance and exit of the ramp.
/// Represents the upper left blue ramp of the [Board].
/// {@endtemplate}
class JetpackRamp extends Component with HasGameRef<PinballGame> {
/// {@macro jetpack_ramp}
@ -15,21 +14,13 @@ class JetpackRamp extends Component with HasGameRef<PinballGame> {
required this.position,
});
final double _radius = 200;
final double _width = 80;
// TODO(ruialonso): Avoid using radians.
final double _angle = radians(210);
final double _rotation = radians(-10);
/// The position of this [JetpackRamp]
/// The position of this [JetpackRamp].
final Vector2 position;
static const _layer = Layer.jetpack;
@override
Future<void> onLoad() async {
gameRef.addContactCallback(
RampOpeningBallContactCallback<JetpackRampOpening>(),
RampOpeningBallContactCallback<_JetpackRampOpening>(),
);
final curvePath = Pathway.arc(
@ -37,24 +28,22 @@ class JetpackRamp extends Component with HasGameRef<PinballGame> {
// TODO(ruialonso): Use a bezier curve once control points are defined.
color: const Color.fromARGB(255, 8, 218, 241),
center: position,
width: _width,
radius: _radius,
angle: _angle,
rotation: _rotation,
width: 80,
radius: 200,
angle: 7 * math.pi / 6,
rotation: -math.pi / 18,
)
..initialPosition = position
..layer = _layer;
final leftOpening = JetpackRampOpening(
orientation: RampOrientation.down,
rotation: radians(15),
..layer = Layer.jetpack;
final leftOpening = _JetpackRampOpening(
rotation: 15 * math.pi / 180,
)
..initialPosition = position + Vector2(-25.7, 25)
..initialPosition = position + Vector2(-27, 21)
..layer = Layer.opening;
final rightOpening = JetpackRampOpening(
orientation: RampOrientation.down,
rotation: radians(-9),
final rightOpening = _JetpackRampOpening(
rotation: -math.pi / 20,
)
..initialPosition = position + Vector2(-10, 26.2)
..initialPosition = position + Vector2(-11, 22.5)
..layer = Layer.opening;
await addAll([
@ -69,32 +58,21 @@ class JetpackRamp extends Component with HasGameRef<PinballGame> {
/// [RampOpening] with [Layer.jetpack] to filter [Ball] collisions
/// inside [JetpackRamp].
/// {@endtemplate}
class JetpackRampOpening extends RampOpening {
class _JetpackRampOpening extends RampOpening {
/// {@macro jetpack_ramp_opening}
JetpackRampOpening({
required RampOrientation orientation,
double rotation = 0,
_JetpackRampOpening({
required double rotation,
}) : _rotation = rotation,
_orientation = orientation,
super(
pathwayLayer: Layer.jetpack,
orientation: RampOrientation.down,
);
/// Orientation of entrance/exit of [JetpackRamp] where
/// this [JetpackRampOpening] is placed.
final RampOrientation _orientation;
/// Rotation of the [RampOpening] to place it right at the
/// entrance/exit of [JetpackRamp].
final double _rotation;
/// Size of the [RampOpening] placed at the entrance/exit of [JetpackRamp].
// TODO(ruialonso): Avoid magic number 3, should be propotional to
// [JetpackRamp].
final Vector2 _size = Vector2(3, .1);
@override
RampOrientation get orientation => _orientation;
static final Vector2 _size = Vector2(3, .1);
@override
Shape get shape => PolygonShape()

@ -1,15 +1,13 @@
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
/// {@template launcher_ramp}
/// Represent the launcher green and upper right yellow ramps for the game.
///
/// Group of [Component]s composed by a [Pathway.arc] as the upper curve ramp,
/// a [Pathway.straight] for the launcher straight ramp, and two
/// [LauncherRampOpening] at the entrance and exit of the ramp, to detect when
/// a ball gets into/out of the ramp.
/// The yellow left ramp, where the [Ball] goes through when launched from the
/// [Plunger].
/// {@endtemplate}
class LauncherRamp extends Component with HasGameRef<PinballGame> {
/// {@macro launcher_ramp}
@ -17,48 +15,39 @@ class LauncherRamp extends Component with HasGameRef<PinballGame> {
required this.position,
});
final double _radius = 300;
final double _width = 80;
final double _angle = radians(200);
/// The position of this [LauncherRamp]
/// The position of this [LauncherRamp].
final Vector2 position;
static const _layer = Layer.launcher;
@override
Future<void> onLoad() async {
const layer = Layer.launcher;
gameRef.addContactCallback(
RampOpeningBallContactCallback<LauncherRampOpening>(),
RampOpeningBallContactCallback<_LauncherRampOpening>(),
);
final straightPath = Pathway.straight(
color: const Color.fromARGB(255, 34, 255, 0),
start: Vector2(0, 0),
end: Vector2(0, 600),
end: Vector2(0, 700),
width: 80,
)
..initialPosition = position
..layer = _layer;
..layer = layer;
final curvedPath = Pathway.arc(
color: const Color.fromARGB(255, 251, 255, 0),
center: position + Vector2(-24, -6),
radius: _radius,
angle: _angle,
width: _width,
center: position + Vector2(-29, -8),
radius: 300,
angle: 10 * math.pi / 9,
width: 80,
)
..initialPosition = position + Vector2(-28.8, -6)
..layer = _layer;
final leftOpening = LauncherRampOpening(
orientation: RampOrientation.down,
rotation: radians(13),
)
..initialPosition = position + Vector2(-46.5, -8.5)
..layer = layer;
final leftOpening = _LauncherRampOpening(rotation: 13 * math.pi / 180)
..initialPosition = position + Vector2(-72.5, 12)
..layer = Layer.opening;
final rightOpening = LauncherRampOpening(
orientation: RampOrientation.down,
)
..initialPosition = position + Vector2(4, 0)
final rightOpening = _LauncherRampOpening(rotation: 0)
..initialPosition = position + Vector2(-46.8, 17)
..layer = Layer.opening;
await addAll([
@ -74,41 +63,28 @@ class LauncherRamp extends Component with HasGameRef<PinballGame> {
/// [RampOpening] with [Layer.launcher] to filter [Ball]s collisions
/// inside [LauncherRamp].
/// {@endtemplate}
class LauncherRampOpening extends RampOpening {
class _LauncherRampOpening extends RampOpening {
/// {@macro launcher_ramp_opening}
LauncherRampOpening({
double rotation = 0,
required RampOrientation orientation,
_LauncherRampOpening({
required double rotation,
}) : _rotation = rotation,
_orientation = orientation,
super(
pathwayLayer: Layer.launcher,
orientation: RampOrientation.down,
);
/// Orientation of entrance/exit of [LauncherRamp] where
/// this [LauncherRampOpening] is placed.
final RampOrientation _orientation;
/// Rotation of the [RampOpening] to place it right at the
/// entrance/exit of [LauncherRamp].
final double _rotation;
/// Size of the [RampOpening] placed at the entrance/exit of [JetpackRamp].
// TODO(ruialonso): Avoid magic number 3, should be propotional to
// [JetpackRamp].
final Vector2 _size = Vector2(3, .1);
@override
RampOrientation get orientation => _orientation;
static final Vector2 _size = Vector2(3, .1);
@override
Shape get shape {
final area = PolygonShape()..setAsBoxXY(_size.x, _size.y);
// TODO(alestiago): Use shape.rotate() once it's implemented.
for (final vertex in area.vertices) {
vertex.rotate(_rotation);
}
return area;
}
Shape get shape => PolygonShape()
..setAsBox(
_size.x,
_size.y,
initialPosition,
_rotation,
);
}

@ -4,14 +4,14 @@ import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.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.
/// {@template ramp_orientation}
/// Determines if a ramp is facing [up] or [down] on the [Board].
/// {@endtemplate}
enum RampOrientation {
/// Facing up on the board.
/// Facing up on the [Board].
up,
/// Facing down on the board.
/// Facing down on the [Board].
down,
}
@ -19,13 +19,16 @@ enum RampOrientation {
/// [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.
/// through this opening.
///
/// By default the [layer] is set to [Layer.board].
/// {@endtemplate}
// TODO(ruialonso): Consider renaming the class.
abstract class RampOpening extends BodyComponent with InitialPosition, Layered {
/// {@macro ramp_opening}
RampOpening({
required Layer pathwayLayer,
required this.orientation,
}) : _pathwayLayer = pathwayLayer {
layer = Layer.board;
}
@ -37,10 +40,10 @@ abstract class RampOpening extends BodyComponent with InitialPosition, Layered {
/// The [Shape] of the [RampOpening].
Shape get shape;
/// Orientation of the [RampOpening] entrance/exit
/// {@macro ramp_orientation}
// TODO(ruimiguel): Try to remove the need of [RampOrientation] for collision
// calculations.
RampOrientation get orientation;
final RampOrientation orientation;
@override
Body createBody() {
@ -85,8 +88,8 @@ class RampOpeningBallContactCallback<Opening extends RampOpening>
@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;
? ball.body.position.y > opening.initialPosition.y
: ball.body.position.y < opening.initialPosition.y;
if (isBallOutsideOpening) ball.layer = Layer.board;
}

@ -102,15 +102,15 @@ class PinballGame extends Forge2DGame
position: screenToWorld(
Vector2(
camera.viewport.effectiveSize.x / 2 - 150,
camera.viewport.effectiveSize.y / 2 - 150,
camera.viewport.effectiveSize.y / 2 - 250,
),
),
);
final launcherRamp = LauncherRamp(
position: screenToWorld(
Vector2(
camera.viewport.effectiveSize.x / 2 + 373,
camera.viewport.effectiveSize.y / 2 - 155,
camera.viewport.effectiveSize.x / 2 + 400,
camera.viewport.effectiveSize.y / 2 - 330,
),
),
);
@ -124,7 +124,7 @@ class PinballGame extends Forge2DGame
);
plunger.initialPosition = screenToWorld(
Vector2(
camera.viewport.effectiveSize.x / 1.035,
camera.viewport.effectiveSize.x / 2 + 450,
camera.viewport.effectiveSize.y - plunger.compressionDistance,
),
);

@ -9,8 +9,6 @@ import 'package:pinball/game/game.dart';
import '../../helpers/helpers.dart';
class MockJetpackRampArea extends Mock implements JetpackRampOpening {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(PinballGameTest.create);
@ -49,7 +47,7 @@ void main() {
);
flameTester.test(
'has a two sensors for the ramp',
'has a two RampOpenings for the ramp',
(game) async {
final ramp = JetpackRamp(
position: Vector2.zero(),
@ -57,27 +55,10 @@ void main() {
await game.ready();
await game.ensureAdd(ramp);
final rampAreas =
ramp.children.whereType<JetpackRampOpening>().toList();
final rampAreas = ramp.children.whereType<RampOpening>();
expect(rampAreas.length, 2);
},
);
});
});
group('JetpackRampOpening', () {
flameTester.test(
'orientation is down',
(game) async {
final position = Vector2.all(10);
final ramp = JetpackRampOpening(
orientation: RampOrientation.down,
)..initialPosition = position;
await game.ready();
await game.ensureAdd(ramp);
expect(ramp.orientation, RampOrientation.down);
},
);
});
}

@ -9,8 +9,6 @@ import 'package:pinball/game/game.dart';
import '../../helpers/helpers.dart';
class MockLauncherRampArea extends Mock implements LauncherRampOpening {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(PinballGameTest.create);
@ -60,7 +58,7 @@ void main() {
);
flameTester.test(
'has a two sensors for the ramp',
'has a two RampOpenings for the ramp',
(game) async {
final ramp = LauncherRamp(
position: Vector2.zero(),
@ -68,27 +66,10 @@ void main() {
await game.ready();
await game.ensureAdd(ramp);
final rampAreas =
ramp.children.whereType<LauncherRampOpening>().toList();
final rampAreas = ramp.children.whereType<RampOpening>().toList();
expect(rampAreas.length, 2);
},
);
});
});
group('LauncherRampOpening', () {
flameTester.test(
'orientation is down',
(game) async {
final position = Vector2.all(10);
final ramp = LauncherRampOpening(
orientation: RampOrientation.down,
)..initialPosition = position;
await game.ready();
await game.ensureAdd(ramp);
expect(ramp.orientation, RampOrientation.down);
},
);
});
}

Loading…
Cancel
Save