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

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

@ -4,14 +4,14 @@ 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';
/// Indicates the orientation of a ramp entrance/exit. /// {@template ramp_orientation}
/// /// Determines if a ramp is facing [up] or [down] on the [Board].
/// Used to know if a ramp is facing up or down on the board. /// {@endtemplate}
enum RampOrientation { enum RampOrientation {
/// Facing up on the board. /// Facing up on the [Board].
up, up,
/// Facing down on the board. /// Facing down on the [Board].
down, down,
} }
@ -19,13 +19,16 @@ enum RampOrientation {
/// [BodyComponent] located at the entrance and exit of a ramp. /// [BodyComponent] located at the entrance and exit of a ramp.
/// ///
/// [RampOpeningBallContactCallback] detects when a [Ball] passes /// [RampOpeningBallContactCallback] detects when a [Ball] passes
/// through this opening. By default openings are [Layer.board] that /// through this opening.
/// means opening are at ground level, not over board. ///
/// By default the [layer] is set to [Layer.board].
/// {@endtemplate} /// {@endtemplate}
// TODO(ruialonso): Consider renaming the class.
abstract class RampOpening extends BodyComponent with InitialPosition, Layered { abstract class RampOpening extends BodyComponent with InitialPosition, Layered {
/// {@macro ramp_opening} /// {@macro ramp_opening}
RampOpening({ RampOpening({
required Layer pathwayLayer, required Layer pathwayLayer,
required this.orientation,
}) : _pathwayLayer = pathwayLayer { }) : _pathwayLayer = pathwayLayer {
layer = Layer.board; layer = Layer.board;
} }
@ -37,10 +40,10 @@ abstract class RampOpening extends BodyComponent with InitialPosition, Layered {
/// The [Shape] of the [RampOpening]. /// The [Shape] of the [RampOpening].
Shape get shape; Shape get shape;
/// Orientation of the [RampOpening] entrance/exit /// {@macro ramp_orientation}
// TODO(ruimiguel): Try to remove the need of [RampOrientation] for collision // TODO(ruimiguel): Try to remove the need of [RampOrientation] for collision
// calculations. // calculations.
RampOrientation get orientation; final RampOrientation orientation;
@override @override
Body createBody() { Body createBody() {
@ -85,8 +88,8 @@ class RampOpeningBallContactCallback<Opening extends RampOpening>
@override @override
void end(Ball ball, Opening opening, Contact _) { void end(Ball ball, Opening opening, Contact _) {
final isBallOutsideOpening = opening.orientation == RampOrientation.up final isBallOutsideOpening = opening.orientation == RampOrientation.up
? ball.body.position.y > opening.body.position.y ? ball.body.position.y > opening.initialPosition.y
: ball.body.position.y < opening.body.position.y; : ball.body.position.y < opening.initialPosition.y;
if (isBallOutsideOpening) ball.layer = Layer.board; if (isBallOutsideOpening) ball.layer = Layer.board;
} }

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

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