From 6cbf4b156f54d4cb19e48c5decfcdabd0294d694 Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Thu, 24 Mar 2022 18:44:34 +0100 Subject: [PATCH] refactor: refactored baseboard with arcshapes --- lib/game/components/baseboard.dart | 22 +-- lib/game/components/components.dart | 1 - lib/game/components/pathway.dart | 209 --------------------- test/game/components/pathway_test.dart | 243 ------------------------- 4 files changed, 10 insertions(+), 465 deletions(-) delete mode 100644 lib/game/components/pathway.dart delete mode 100644 test/game/components/pathway_test.dart diff --git a/lib/game/components/baseboard.dart b/lib/game/components/baseboard.dart index d9dc3512..d4c326e3 100644 --- a/lib/game/components/baseboard.dart +++ b/lib/game/components/baseboard.dart @@ -46,25 +46,23 @@ class Baseboard extends BodyComponent with InitialPosition { final outerEdgeShapeFixtureDef = FixtureDef(outerEdgeShape); fixturesDef.add(outerEdgeShapeFixtureDef); - final upperArcFixtureDefs = Pathway.arc( + final upperArcShape = ArcShape( center: Vector2(1.76 * direction, 3.25), - width: 0, - radius: 6.1, + arcRadius: 6.1, angle: arcsAngle, rotation: arcsRotation, - singleWall: true, - ).createFixtureDefs(); - fixturesDef.addAll(upperArcFixtureDefs); + ); + final upperArcFixtureDefs = FixtureDef(upperArcShape); + fixturesDef.add(upperArcFixtureDefs); - final lowerArcFixtureDefs = Pathway.arc( + final lowerArcShape = ArcShape( center: Vector2(1.85 * direction, -2.15), - width: 0, - radius: 4.5, + arcRadius: 4.5, angle: arcsAngle, rotation: arcsRotation, - singleWall: true, - ).createFixtureDefs(); - fixturesDef.addAll(lowerArcFixtureDefs); + ); + final lowerArcFixtureDefs = FixtureDef(lowerArcShape); + fixturesDef.add(lowerArcFixtureDefs); final bottomRectangle = PolygonShape() ..setAsBox( diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 1ed293da..1a22149a 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -8,7 +8,6 @@ export 'jetpack_ramp.dart'; export 'joint_anchor.dart'; export 'kicker.dart'; export 'launcher_ramp.dart'; -export 'pathway.dart'; export 'plunger.dart'; export 'ramp_opening.dart'; export 'round_bumper.dart'; diff --git a/lib/game/components/pathway.dart b/lib/game/components/pathway.dart deleted file mode 100644 index 54c81464..00000000 --- a/lib/game/components/pathway.dart +++ /dev/null @@ -1,209 +0,0 @@ -import 'package:flame/extensions.dart'; -import 'package:flame_forge2d/flame_forge2d.dart'; -import 'package:flutter/material.dart'; -import 'package:geometry/geometry.dart'; -import 'package:pinball_components/pinball_components.dart'; - -/// {@template pathway} -/// [Pathway] creates lines of various shapes. -/// -/// [BodyComponent]s such as a Ball can collide and move along a [Pathway]. -/// {@endtemplate} -class Pathway extends BodyComponent with InitialPosition, Layered { - Pathway._({ - // TODO(ruialonso): remove color when assets added. - Color? color, - required List> paths, - }) : _paths = paths { - paint = Paint() - ..color = color ?? const Color.fromARGB(0, 0, 0, 0) - ..style = PaintingStyle.stroke; - } - - /// Creates a uniform unidirectional (straight) [Pathway]. - /// - /// Does so with two [ChainShape] separated by a [width]. Can - /// be rotated by a given [rotation] in radians. - /// - /// If [singleWall] is true, just one [ChainShape] is created. - factory Pathway.straight({ - Color? color, - required Vector2 start, - required Vector2 end, - required double width, - double rotation = 0, - bool singleWall = false, - }) { - final paths = >[]; - - // TODO(ruialonso): Refactor repetitive logic - final firstWall = [ - start.clone(), - end.clone(), - ].map((vector) => vector..rotate(rotation)).toList(); - paths.add(firstWall); - - if (!singleWall) { - final secondWall = [ - start + Vector2(width, 0), - end + Vector2(width, 0), - ].map((vector) => vector..rotate(rotation)).toList(); - paths.add(secondWall); - } - - return Pathway._( - color: color, - paths: paths, - ); - } - - /// Creates an arc [Pathway]. - /// - /// The [angle], in radians, specifies the size of the arc. For example, two - /// pi returns a complete circumference. - /// - /// Does so with two [ChainShape] separated by a [width]. Which can be - /// rotated by a given [rotation] in radians. - /// - /// The outer radius is specified by [radius], whilst the inner one is - /// equivalent to the [radius] minus the [width]. - /// - /// If [singleWall] is true, just one [ChainShape] is created. - factory Pathway.arc({ - Color? color, - required Vector2 center, - required double width, - required double radius, - required double angle, - double rotation = 0, - bool singleWall = false, - }) { - final paths = >[]; - - // TODO(ruialonso): Refactor repetitive logic - final outerWall = calculateArc( - center: center, - radius: radius, - angle: angle, - offsetAngle: rotation, - ); - paths.add(outerWall); - - if (!singleWall) { - final innerWall = calculateArc( - center: center, - radius: radius - width, - angle: angle, - offsetAngle: rotation, - ); - paths.add(innerWall); - } - - return Pathway._( - color: color, - paths: paths, - ); - } - - /// Creates a bezier curve [Pathway]. - /// - /// Does so with two [ChainShape] separated by a [width]. Which can be - /// rotated by a given [rotation] in radians. - /// - /// First and last [controlPoints] set the beginning and end of the curve, - /// inner points between them set its final shape. - /// - /// If [singleWall] is true, just one [ChainShape] is created. - factory Pathway.bezierCurve({ - Color? color, - required List controlPoints, - required double width, - double rotation = 0, - bool singleWall = false, - }) { - final paths = >[]; - - // TODO(ruialonso): Refactor repetitive logic - final firstWall = calculateBezierCurve(controlPoints: controlPoints) - .map((vector) => vector..rotate(rotation)) - .toList(); - paths.add(firstWall); - - if (!singleWall) { - final secondWall = calculateBezierCurve( - controlPoints: controlPoints - .map((vector) => vector + Vector2(width, -width)) - .toList(), - ).map((vector) => vector..rotate(rotation)).toList(); - paths.add(secondWall); - } - - return Pathway._( - color: color, - paths: paths, - ); - } - - /// Creates an ellipse [Pathway]. - /// - /// Does so with two [ChainShape]s separated by a [width]. Can - /// be rotated by a given [rotation] in radians. - /// - /// If [singleWall] is true, just one [ChainShape] is created. - factory Pathway.ellipse({ - Color? color, - required Vector2 center, - required double width, - required double majorRadius, - required double minorRadius, - double rotation = 0, - bool singleWall = false, - }) { - final paths = >[]; - - // TODO(ruialonso): Refactor repetitive logic - final outerWall = calculateEllipse( - center: center, - majorRadius: majorRadius, - minorRadius: minorRadius, - ).map((vector) => vector..rotate(rotation)).toList(); - paths.add(outerWall); - - if (!singleWall) { - final innerWall = calculateEllipse( - center: center, - majorRadius: majorRadius - width, - minorRadius: minorRadius - width, - ).map((vector) => vector..rotate(rotation)).toList(); - paths.add(innerWall); - } - - return Pathway._( - color: color, - paths: paths, - ); - } - - final List> _paths; - - /// Constructs different [ChainShape]s to form the [Pathway] shape. - List createFixtureDefs() { - final fixturesDef = []; - - for (final path in _paths) { - final chain = ChainShape()..createChain(path); - fixturesDef.add(FixtureDef(chain)); - } - - return fixturesDef; - } - - @override - Body createBody() { - final bodyDef = BodyDef()..position = initialPosition; - final body = world.createBody(bodyDef); - createFixtureDefs().forEach(body.createFixture); - - return body; - } -} diff --git a/test/game/components/pathway_test.dart b/test/game/components/pathway_test.dart deleted file mode 100644 index 63e74d4d..00000000 --- a/test/game/components/pathway_test.dart +++ /dev/null @@ -1,243 +0,0 @@ -// ignore_for_file: cascade_invocations, prefer_const_constructors -import 'dart:math' as math; -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(Forge2DGame.new); - - group('Pathway', () { - const width = 50.0; - - group('straight', () { - flameTester.test( - 'loads correctly', - (game) async { - final pathway = Pathway.straight( - start: Vector2(10, 10), - end: Vector2(20, 20), - width: width, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(game.contains(pathway), isTrue); - }, - ); - - group('color', () { - flameTester.test( - 'has transparent color by default when no color is specified', - (game) async { - final pathway = Pathway.straight( - start: Vector2(10, 10), - end: Vector2(20, 20), - width: width, - ); - await game.ready(); - 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 when is specified', - (game) async { - const defaultColor = Colors.blue; - - final pathway = Pathway.straight( - color: defaultColor, - start: Vector2(10, 10), - end: Vector2(20, 20), - width: width, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(game.contains(pathway), isTrue); - expect(pathway.paint, isNotNull); - expect(pathway.paint.color.value, equals(defaultColor.value)); - }, - ); - }); - - group('body', () { - flameTester.test( - 'is static', - (game) async { - final pathway = Pathway.straight( - start: Vector2(10, 10), - end: Vector2(20, 20), - width: width, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(pathway.body.bodyType, equals(BodyType.static)); - }, - ); - }); - - group('fixtures', () { - flameTester.test( - 'has only one ChainShape when singleWall is true', - (game) async { - final pathway = Pathway.straight( - start: Vector2(10, 10), - end: Vector2(20, 20), - width: width, - singleWall: true, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(pathway.body.fixtures.length, 1); - final fixture = pathway.body.fixtures[0]; - expect(fixture, isA()); - expect(fixture.shape.shapeType, equals(ShapeType.chain)); - }, - ); - - flameTester.test( - 'has two ChainShape when singleWall is false (default)', - (game) async { - final pathway = Pathway.straight( - start: Vector2(10, 10), - end: Vector2(20, 20), - width: width, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(pathway.body.fixtures.length, 2); - for (final fixture in pathway.body.fixtures) { - expect(fixture, isA()); - expect(fixture.shape.shapeType, equals(ShapeType.chain)); - } - }, - ); - }); - }); - - group('arc', () { - flameTester.test( - 'loads correctly', - (game) async { - final pathway = Pathway.arc( - center: Vector2.zero(), - width: width, - radius: 100, - angle: math.pi / 2, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(game.contains(pathway), isTrue); - }, - ); - - group('body', () { - flameTester.test( - 'is static', - (game) async { - final pathway = Pathway.arc( - center: Vector2.zero(), - width: width, - radius: 100, - angle: math.pi / 2, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(pathway.body.bodyType, equals(BodyType.static)); - }, - ); - }); - }); - - group('ellipse', () { - flameTester.test( - 'loads correctly', - (game) async { - final pathway = Pathway.ellipse( - center: Vector2.zero(), - width: width, - majorRadius: 150, - minorRadius: 70, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(game.contains(pathway), isTrue); - }, - ); - - group('body', () { - flameTester.test( - 'is static', - (game) async { - final pathway = Pathway.ellipse( - center: Vector2.zero(), - width: width, - majorRadius: 150, - minorRadius: 70, - ); - await game.ready(); - 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( - controlPoints: controlPoints, - width: width, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(game.contains(pathway), isTrue); - }, - ); - - group('body', () { - flameTester.test( - 'is static', - (game) async { - final pathway = Pathway.bezierCurve( - controlPoints: controlPoints, - width: width, - ); - await game.ready(); - await game.ensureAdd(pathway); - - expect(pathway.body.bodyType, equals(BodyType.static)); - }, - ); - }); - }); - }); -}