chore: applied changes from GH comments, doc descriptions, var names, asserts, etc

pull/14/head
RuiAlonso 3 years ago
parent 631688f821
commit 4faf703648

@ -4,11 +4,12 @@ import 'package:flutter/material.dart';
import 'package:maths/maths.dart';
/// {@template pathway}
/// [Pathway] creates different shapes that sets the pathwayways that ball
/// can follow or collide to like walls.
/// [Pathway] creates lines of various shapes that the [Ball] can collide
/// with and move along.
/// {@endtemplate}
class Pathway extends BodyComponent {
Pathway._({
// TODO(ruialonso): remove color when assets added.
Color? color,
required Vector2 position,
required List<List<Vector2>> paths,
@ -20,10 +21,11 @@ class Pathway extends BodyComponent {
}
/// {@macro pathway}
/// [Pathway.straight] creates a straight pathway for the ball given
/// a [position] for the body, between a [start] and [end] points.
/// It creates two [ChainShape] separated by a [pathwayWidth]. If [singleWall]
/// is true, just one [ChainShape] is created
/// [Pathway.straight] creates a straight pathway for the ball.
///
/// given a [position] for the body, between a [start] and [end] points.
/// It creates two [ChainShape] separated by a [pathwayWidth].
/// If [singleWall] is true, just one [ChainShape] is created
/// (like a wall instead of a pathway)
/// The pathway could be rotated by [rotation] in degrees.
factory Pathway.straight({
@ -39,15 +41,15 @@ class Pathway extends BodyComponent {
final wall1 = [
start.clone(),
end.clone(),
];
paths.add(wall1.map((e) => e..rotate(radians(rotation))).toList());
].map((vector) => vector..rotate(radians(rotation))).toList();
paths.add(wall1);
if (!singleWall) {
final wall2 = [
start + Vector2(pathwayWidth, 0),
end + Vector2(pathwayWidth, 0),
];
paths.add(wall2.map((e) => e..rotate(radians(rotation))).toList());
].map((vector) => vector..rotate(radians(rotation))).toList();
paths.add(wall2);
}
return Pathway._(
@ -58,9 +60,11 @@ class Pathway extends BodyComponent {
}
/// {@macro pathway}
/// [Pathway.straight] creates an arc pathway for the ball given a [position]
/// for the body, a [radius] for the circumference and an [angle] to specify
/// the size of the semi circumference.
/// [Pathway.arc] creates an arc pathway for the ball.
///
/// The arc is created given a [position] for the body, a [radius] for the
/// circumference and an [angle] to specify the size of it (360 will return
/// a completed circumference and minor angles a semi circumference ).
/// It creates two [ChainShape] separated by a [pathwayWidth], like a circular
/// crown. The specified [radius] is for the outer arc, the inner one will
/// have a radius of radius-pathwayWidth.
@ -86,11 +90,9 @@ class Pathway extends BodyComponent {
paths.add(wall1);
if (!singleWall) {
final minRadius = radius - pathwayWidth;
final wall2 = calculateArc(
center: position,
radius: minRadius,
radius: radius - pathwayWidth,
angle: angle,
offsetAngle: rotation,
);
@ -105,12 +107,14 @@ class Pathway extends BodyComponent {
}
/// {@macro pathway}
/// [Pathway.straight] creates a bezier curve pathway for the ball given a
/// [position] for the body, with control point specified by [controlPoints].
/// [Pathway.bezierCurve] creates a bezier curve pathway for the ball.
///
/// The curve is created given a [position] for the body, and
/// with a list of control points specified by [controlPoints].
/// First and last points set the beginning and end of the curve, all the
/// inner points between them set the bezier curve final shape.
/// It creates two [ChainShape] separated by a [pathwayWidth]. If [singleWall]
/// is true, just one [ChainShape] is created
/// It creates two [ChainShape] separated by a [pathwayWidth].
/// If [singleWall] is true, just one [ChainShape] is created
/// (like a wall instead of a pathway)
/// The pathway could be rotated by [rotation] in degrees.
factory Pathway.bezierCurve({
@ -123,17 +127,18 @@ class Pathway extends BodyComponent {
}) {
final paths = <List<Vector2>>[];
final wall1 = calculateBezierCurve(controlPoints: controlPoints);
paths.add(wall1.map((e) => e..rotate(radians(rotation))).toList());
final wall1 = calculateBezierCurve(controlPoints: controlPoints)
.map((vector) => vector..rotate(radians(rotation)))
.toList();
paths.add(wall1);
var wall2 = <Vector2>[];
if (!singleWall) {
wall2 = calculateBezierCurve(
final wall2 = calculateBezierCurve(
controlPoints: controlPoints
.map((e) => e + Vector2(pathwayWidth, -pathwayWidth))
.map((vector) => vector + Vector2(pathwayWidth, -pathwayWidth))
.toList(),
);
paths.add(wall2.map((e) => e..rotate(radians(rotation))).toList());
).map((vector) => vector..rotate(radians(rotation))).toList();
paths.add(wall2);
}
return Pathway._(

@ -0,0 +1,248 @@
// ignore_for_file: cascade_invocations, prefer_const_constructors
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/game/game.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(PinballGame.new);
group('Pathway', () {
const pathwayWidth = 50.0;
group('straight', () {
group('color', () {
flameTester.test(
'has transparent color by default if not specified',
(game) async {
final pathway = Pathway.straight(
position: Vector2.zero(),
start: Vector2(10, 10),
end: Vector2(20, 20),
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
expect(game.contains(pathway), isTrue);
expect(pathway.paint, isNotNull);
expect(
pathway.paint.color,
equals(Color.fromARGB(0, 0, 0, 0)),
);
},
);
flameTester.test(
'has a color if set',
(game) async {
const defaultColor = Colors.blue;
final pathway = Pathway.straight(
color: defaultColor,
position: Vector2.zero(),
start: Vector2(10, 10),
end: Vector2(20, 20),
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
expect(game.contains(pathway), isTrue);
expect(pathway.paint, isNotNull);
expect(pathway.paint.color.value, equals(defaultColor.value));
},
);
});
flameTester.test(
'loads correctly',
(game) async {
final pathway = Pathway.straight(
position: Vector2.zero(),
start: Vector2(10, 10),
end: Vector2(20, 20),
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
expect(game.contains(pathway), isTrue);
},
);
group('body', () {
flameTester.test(
'positions correctly',
(game) async {
final position = Vector2.all(10);
final pathway = Pathway.straight(
position: position,
start: Vector2(10, 10),
end: Vector2(20, 20),
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
game.contains(pathway);
expect(pathway.body.position, position);
},
);
flameTester.test(
'is static',
(game) async {
final pathway = Pathway.straight(
position: Vector2.zero(),
start: Vector2(10, 10),
end: Vector2(20, 20),
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
expect(pathway.body.bodyType, equals(BodyType.static));
},
);
});
group('fixtures', () {
flameTester.test(
'exists only one ChainShape if just one wall',
(game) async {
final pathway = Pathway.straight(
position: Vector2.zero(),
start: Vector2(10, 10),
end: Vector2(20, 20),
pathwayWidth: pathwayWidth,
singleWall: true,
);
await game.ensureAdd(pathway);
expect(pathway.body.fixtures.length, 1);
final fixture = pathway.body.fixtures[0];
expect(fixture, isA<Fixture>());
expect(fixture.shape.shapeType, equals(ShapeType.chain));
},
);
flameTester.test(
'exists two ChainShape if there is by default two walls',
(game) async {
final pathway = Pathway.straight(
position: Vector2.zero(),
start: Vector2(10, 10),
end: Vector2(20, 20),
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
expect(pathway.body.fixtures.length, 2);
for (final fixture in pathway.body.fixtures) {
expect(fixture, isA<Fixture>());
expect(fixture.shape.shapeType, equals(ShapeType.chain));
}
},
);
});
});
group('arc', () {
flameTester.test(
'loads correctly',
(game) async {
final pathway = Pathway.arc(
position: Vector2.zero(),
pathwayWidth: pathwayWidth,
radius: 100,
angle: 90,
);
await game.ensureAdd(pathway);
expect(game.contains(pathway), isTrue);
},
);
group('body', () {
flameTester.test(
'positions correctly',
(game) async {
final position = Vector2.all(10);
final pathway = Pathway.arc(
position: position,
pathwayWidth: pathwayWidth,
radius: 100,
angle: 90,
);
await game.ensureAdd(pathway);
game.contains(pathway);
expect(pathway.body.position, position);
},
);
flameTester.test(
'is static',
(game) async {
final pathway = Pathway.arc(
position: Vector2.zero(),
pathwayWidth: pathwayWidth,
radius: 100,
angle: 90,
);
await game.ensureAdd(pathway);
expect(pathway.body.bodyType, equals(BodyType.static));
},
);
});
});
group('bezier curve', () {
final controlPoints = [
Vector2(0, 0),
Vector2(50, 0),
Vector2(0, 50),
Vector2(50, 50),
];
flameTester.test(
'loads correctly',
(game) async {
final pathway = Pathway.bezierCurve(
position: Vector2.zero(),
controlPoints: controlPoints,
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
expect(game.contains(pathway), isTrue);
},
);
group('body', () {
flameTester.test(
'positions correctly',
(game) async {
final position = Vector2.all(10);
final pathway = Pathway.bezierCurve(
position: position,
controlPoints: controlPoints,
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
game.contains(pathway);
expect(pathway.body.position, position);
},
);
flameTester.test(
'is static',
(game) async {
final pathway = Pathway.bezierCurve(
position: Vector2.zero(),
controlPoints: controlPoints,
pathwayWidth: pathwayWidth,
);
await game.ensureAdd(pathway);
expect(pathway.body.bodyType, equals(BodyType.static));
},
);
});
});
});
}
Loading…
Cancel
Save