diff --git a/lib/game/components/wall.dart b/lib/game/components/wall.dart index f5d03c80..030edc50 100644 --- a/lib/game/components/wall.dart +++ b/lib/game/components/wall.dart @@ -2,8 +2,8 @@ import 'package:flame/extensions.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; -import 'package:pinball/game/components/components.dart'; -import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart' hide Assets; /// {@template wall} /// A continuous generic and [BodyType.static] barrier that divides a game area. diff --git a/lib/game/game_assets.dart b/lib/game/game_assets.dart index ee7b7900..edfe7947 100644 --- a/lib/game/game_assets.dart +++ b/lib/game/game_assets.dart @@ -13,6 +13,8 @@ extension PinballGameAssetsX on PinballGame { images.load(components.Assets.images.flipper.right.keyName), images.load(components.Assets.images.baseboard.left.keyName), images.load(components.Assets.images.baseboard.right.keyName), + images.load(components.Assets.images.dino.dinoLandTop.keyName), + images.load(components.Assets.images.dino.dinoLandBottom.keyName), images.load(Assets.images.components.background.path), ]); } diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index c2bbe8e0..b5162053 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -66,6 +66,13 @@ class PinballGame extends Forge2DGame Future _addGameBoundaries() async { await add(BottomWall()); createBoundaries(this).forEach(add); + unawaited( + addFromBlueprint( + DinoWalls( + position: Vector2(-2.4, 0), + ), + ), + ); } Future _addPlunger() async { diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index 370d8fcf..97be7f3e 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -3,6 +3,8 @@ /// FlutterGen /// ***************************************************** +// ignore_for_file: directives_ordering,unnecessary_import + import 'package:flutter/widgets.dart'; class $AssetsImagesGen { @@ -15,6 +17,7 @@ class $AssetsImagesGen { class $AssetsImagesComponentsGen { const $AssetsImagesComponentsGen(); + /// File path: assets/images/components/background.png AssetGenImage get background => const AssetGenImage('assets/images/components/background.png'); } diff --git a/packages/geometry/lib/src/geometry.dart b/packages/geometry/lib/src/geometry.dart index 6975f8cb..edc176e7 100644 --- a/packages/geometry/lib/src/geometry.dart +++ b/packages/geometry/lib/src/geometry.dart @@ -82,7 +82,7 @@ List calculateEllipse({ /// For more information read: https://en.wikipedia.org/wiki/B%C3%A9zier_curve List calculateBezierCurve({ required List controlPoints, - double step = 0.001, + double step = 0.01, }) { assert( 0 <= step && step <= 1, diff --git a/packages/geometry/test/src/geometry_test.dart b/packages/geometry/test/src/geometry_test.dart index 7a49b2b2..e702f043 100644 --- a/packages/geometry/test/src/geometry_test.dart +++ b/packages/geometry/test/src/geometry_test.dart @@ -98,14 +98,14 @@ void main() { ); }); - test('returns by default 1000 points as indicated by step', () { + test('returns by default 100 points as indicated by step', () { final points = calculateBezierCurve( controlPoints: [ Vector2(0, 0), Vector2(10, 10), ], ); - expect(points.length, 1000); + expect(points.length, 100); }); test('returns as many points as indicated by step', () { @@ -114,9 +114,9 @@ void main() { Vector2(0, 0), Vector2(10, 10), ], - step: 0.01, + step: 0.001, ); - expect(points.length, 100); + expect(points.length, 1000); }); }); diff --git a/packages/pinball_components/assets/images/dino/dino-land-bottom.png b/packages/pinball_components/assets/images/dino/dino-land-bottom.png new file mode 100644 index 00000000..1839dda3 Binary files /dev/null and b/packages/pinball_components/assets/images/dino/dino-land-bottom.png differ diff --git a/packages/pinball_components/assets/images/dino/dino-land-top.png b/packages/pinball_components/assets/images/dino/dino-land-top.png new file mode 100644 index 00000000..85c2619a Binary files /dev/null and b/packages/pinball_components/assets/images/dino/dino-land-top.png differ diff --git a/packages/pinball_components/lib/gen/assets.gen.dart b/packages/pinball_components/lib/gen/assets.gen.dart index 27a54591..8bd651ed 100644 --- a/packages/pinball_components/lib/gen/assets.gen.dart +++ b/packages/pinball_components/lib/gen/assets.gen.dart @@ -14,7 +14,7 @@ class $AssetsImagesGen { AssetGenImage get ball => const AssetGenImage('assets/images/ball.png'); $AssetsImagesBaseboardGen get baseboard => const $AssetsImagesBaseboardGen(); - + $AssetsImagesDinoGen get dino => const $AssetsImagesDinoGen(); $AssetsImagesFlipperGen get flipper => const $AssetsImagesFlipperGen(); /// File path: assets/images/flutter_sign_post.png @@ -42,6 +42,18 @@ class $AssetsImagesBaseboardGen { const AssetGenImage('assets/images/baseboard/right.png'); } +class $AssetsImagesDinoGen { + const $AssetsImagesDinoGen(); + + /// File path: assets/images/dino/dino-land-bottom.png + AssetGenImage get dinoLandBottom => + const AssetGenImage('assets/images/dino/dino-land-bottom.png'); + + /// File path: assets/images/dino/dino-land-top.png + AssetGenImage get dinoLandTop => + const AssetGenImage('assets/images/dino/dino-land-top.png'); +} + class $AssetsImagesFlipperGen { const $AssetsImagesFlipperGen(); diff --git a/packages/pinball_components/lib/src/components/components.dart b/packages/pinball_components/lib/src/components/components.dart index a475f91e..4e38c2c4 100644 --- a/packages/pinball_components/lib/src/components/components.dart +++ b/packages/pinball_components/lib/src/components/components.dart @@ -2,6 +2,7 @@ export 'ball.dart'; export 'baseboard.dart'; export 'board_dimensions.dart'; export 'board_side.dart'; +export 'dino_walls.dart'; export 'fire_effect.dart'; export 'flipper.dart'; export 'flutter_sign_post.dart'; diff --git a/packages/pinball_components/lib/src/components/dino_walls.dart b/packages/pinball_components/lib/src/components/dino_walls.dart new file mode 100644 index 00000000..13f56ff3 --- /dev/null +++ b/packages/pinball_components/lib/src/components/dino_walls.dart @@ -0,0 +1,225 @@ +// ignore_for_file: comment_references, avoid_renaming_method_parameters + +import 'dart:async'; + +import 'package:flame/components.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:pinball_components/gen/assets.gen.dart'; +import 'package:pinball_components/pinball_components.dart' hide Assets; + +/// {@template dinowalls} +/// A [Blueprint] which creates walls for the [ChromeDino]. +/// {@endtemplate} +class DinoWalls extends Forge2DBlueprint { + /// {@macro dinowalls} + DinoWalls({required this.position}); + + /// The [position] where the elements will be created + final Vector2 position; + + @override + void build(_) { + addAll([ + _DinoTopWall()..initialPosition = position, + _DinoBottomWall()..initialPosition = position, + ]); + } +} + +/// {@template dino_top_wall} +/// Wall segment located above [ChromeDino]. +/// {@endtemplate} +class _DinoTopWall extends BodyComponent with InitialPosition { + ///{@macro dino_top_wall} + _DinoTopWall() : super(priority: 2); + + List _createFixtureDefs() { + final fixturesDef = []; + + final topStraightShape = EdgeShape() + ..set( + Vector2(29.5, 35.1), + Vector2(28.4, 35.1), + ); + final topStraightFixtureDef = FixtureDef(topStraightShape); + fixturesDef.add(topStraightFixtureDef); + + final topCurveShape = BezierCurveShape( + controlPoints: [ + topStraightShape.vertex1, + Vector2(17.4, 26.38), + Vector2(25.5, 20.7), + ], + ); + fixturesDef.add(FixtureDef(topCurveShape)); + + final middleCurveShape = BezierCurveShape( + controlPoints: [ + topCurveShape.vertices.last, + Vector2(27.8, 20.1), + Vector2(26.8, 19.5), + ], + ); + fixturesDef.add(FixtureDef(middleCurveShape)); + + final bottomCurveShape = BezierCurveShape( + controlPoints: [ + middleCurveShape.vertices.last, + Vector2(21.15, 16), + Vector2(25.6, 15.2), + ], + ); + fixturesDef.add(FixtureDef(bottomCurveShape)); + + final bottomStraightShape = EdgeShape() + ..set( + bottomCurveShape.vertices.last, + Vector2(31, 14.5), + ); + final bottomStraightFixtureDef = FixtureDef(bottomStraightShape); + fixturesDef.add(bottomStraightFixtureDef); + + return fixturesDef; + } + + @override + Body createBody() { + renderBody = false; + + final bodyDef = BodyDef() + ..userData = this + ..position = initialPosition + ..type = BodyType.static; + + final body = world.createBody(bodyDef); + _createFixtureDefs().forEach( + (fixture) => body.createFixture( + fixture + ..restitution = 0.1 + ..friction = 0, + ), + ); + + return body; + } + + @override + Future onLoad() async { + await super.onLoad(); + await _loadSprite(); + } + + Future _loadSprite() async { + final sprite = await gameRef.loadSprite( + Assets.images.dino.dinoLandTop.keyName, + ); + final spriteComponent = SpriteComponent( + sprite: sprite, + size: Vector2(10.6, 27.7), + anchor: Anchor.center, + position: Vector2(27, -28.2), + ); + + await add(spriteComponent); + } +} + +/// {@template dino_bottom_wall} +/// Wall segment located below [ChromeDino]. +/// {@endtemplate} +class _DinoBottomWall extends BodyComponent with InitialPosition { + ///{@macro dino_top_wall} + _DinoBottomWall() : super(priority: 2); + + List _createFixtureDefs() { + final fixturesDef = []; + + final topStraightControlPoints = [ + Vector2(32.4, 8.3), + Vector2(25, 7.7), + ]; + final topStraightShape = EdgeShape() + ..set( + topStraightControlPoints.first, + topStraightControlPoints.last, + ); + final topStraightFixtureDef = FixtureDef(topStraightShape); + fixturesDef.add(topStraightFixtureDef); + + final topLeftCurveControlPoints = [ + topStraightControlPoints.last, + Vector2(21.8, 7), + Vector2(29.5, -13.8), + ]; + final topLeftCurveShape = BezierCurveShape( + controlPoints: topLeftCurveControlPoints, + ); + fixturesDef.add(FixtureDef(topLeftCurveShape)); + + final bottomLeftStraightControlPoints = [ + topLeftCurveControlPoints.last, + Vector2(31.8, -44.1), + ]; + final bottomLeftStraightShape = EdgeShape() + ..set( + bottomLeftStraightControlPoints.first, + bottomLeftStraightControlPoints.last, + ); + final bottomLeftStraightFixtureDef = FixtureDef(bottomLeftStraightShape); + fixturesDef.add(bottomLeftStraightFixtureDef); + + final bottomStraightControlPoints = [ + bottomLeftStraightControlPoints.last, + Vector2(37.8, -44.1), + ]; + final bottomStraightShape = EdgeShape() + ..set( + bottomStraightControlPoints.first, + bottomStraightControlPoints.last, + ); + final bottomStraightFixtureDef = FixtureDef(bottomStraightShape); + fixturesDef.add(bottomStraightFixtureDef); + + return fixturesDef; + } + + @override + Body createBody() { + renderBody = false; + + final bodyDef = BodyDef() + ..userData = this + ..position = initialPosition + ..type = BodyType.static; + + final body = world.createBody(bodyDef); + _createFixtureDefs().forEach( + (fixture) => body.createFixture( + fixture + ..restitution = 0.1 + ..friction = 0, + ), + ); + + return body; + } + + @override + Future onLoad() async { + await super.onLoad(); + await _loadSprite(); + } + + Future _loadSprite() async { + final sprite = await gameRef.loadSprite( + Assets.images.dino.dinoLandBottom.keyName, + ); + final spriteComponent = SpriteComponent( + sprite: sprite, + size: Vector2(15.6, 54.8), + anchor: Anchor.center, + )..position = Vector2(31.7, 18); + + await add(spriteComponent); + } +} diff --git a/packages/pinball_components/pubspec.yaml b/packages/pinball_components/pubspec.yaml index c0eab284..d1f138d9 100644 --- a/packages/pinball_components/pubspec.yaml +++ b/packages/pinball_components/pubspec.yaml @@ -27,6 +27,7 @@ flutter: assets: - assets/images/ - assets/images/baseboard/ + - assets/images/dino/ - assets/images/flipper/ flutter_gen: diff --git a/packages/pinball_components/test/src/components/dino_walls_test.dart b/packages/pinball_components/test/src/components/dino_walls_test.dart new file mode 100644 index 00000000..af80444b --- /dev/null +++ b/packages/pinball_components/test/src/components/dino_walls_test.dart @@ -0,0 +1,28 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/pinball_components.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + group('DinoWalls', () { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(TestGame.new); + + flameTester.test( + 'loads correctly', + (game) async { + final dinoWalls = DinoWalls(position: Vector2.zero()); + await game.addFromBlueprint(dinoWalls); + await game.ready(); + + for (final wall in dinoWalls.components) { + expect(game.contains(wall), isTrue); + } + }, + ); + }); +} diff --git a/packages/pinball_components/test/src/components/golden/dino-bottom-wall.png b/packages/pinball_components/test/src/components/golden/dino-bottom-wall.png new file mode 100644 index 00000000..14ae9c0d Binary files /dev/null and b/packages/pinball_components/test/src/components/golden/dino-bottom-wall.png differ diff --git a/packages/pinball_components/test/src/components/golden/dino-top-wall.png b/packages/pinball_components/test/src/components/golden/dino-top-wall.png new file mode 100644 index 00000000..0d434d69 Binary files /dev/null and b/packages/pinball_components/test/src/components/golden/dino-top-wall.png differ