// ignore_for_file: avoid_renaming_method_parameters, comment_references import 'dart:math' as math; 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 spaceship_ramp} /// A [Blueprint] which creates the [_SpaceshipRampBackground]. /// {@endtemplate} class SpaceshipRamp extends Forge2DBlueprint { /// {@macro spaceship_ramp} SpaceshipRamp(); /// Base priority for wall while be in the ramp. static const int ballPriorityInsideRamp = 4; @override void build(_) { addAllContactCallback([ RampOpeningBallContactCallback<_SpaceshipRampOpening>(), ]); final rightOpening = _SpaceshipRampOpening( // TODO(ruimiguel): set Board priority when defined. outsidePriority: 1, rotation: math.pi, ) ..initialPosition = Vector2(1.7, 19) ..layer = Layer.opening; final leftOpening = _SpaceshipRampOpening( outsideLayer: Layer.spaceship, outsidePriority: Spaceship.ballPriorityWhenOnSpaceship, rotation: math.pi, ) ..initialPosition = Vector2(-13.7, 19) ..layer = Layer.spaceshipEntranceRamp; final spaceshipRamp = _SpaceshipRampBackground(); final spaceshipRampForegroundRailing = _SpaceshipRampForegroundRailing(); final baseRight = _SpaceshipRampBase()..initialPosition = Vector2(1.7, 20); addAll([ rightOpening, leftOpening, baseRight, spaceshipRamp, spaceshipRampForegroundRailing, ]); } } /// Represents the upper left blue ramp of the [Board] with its background /// railing. class _SpaceshipRampBackground extends BodyComponent with InitialPosition, Layered { _SpaceshipRampBackground() : super(priority: SpaceshipRamp.ballPriorityInsideRamp - 1) { layer = Layer.spaceshipEntranceRamp; } /// Width between walls of the ramp. static const width = 5.0; List _createFixtureDefs() { final fixturesDef = []; final outerLeftCurveShape = BezierCurveShape( controlPoints: [ Vector2(-30.95, 38), Vector2(-32.5, 71.25), Vector2(-14.2, 71.25), ], ); final outerLeftCurveFixtureDef = FixtureDef(outerLeftCurveShape); fixturesDef.add(outerLeftCurveFixtureDef); final outerRightCurveShape = BezierCurveShape( controlPoints: [ outerLeftCurveShape.vertices.last, Vector2(4.7, 71.25), Vector2(6.3, 40), ], ); final outerRightCurveFixtureDef = FixtureDef(outerRightCurveShape); fixturesDef.add(outerRightCurveFixtureDef); return fixturesDef; } @override Body createBody() { final bodyDef = BodyDef() ..userData = this ..position = initialPosition; final body = world.createBody(bodyDef); _createFixtureDefs().forEach(body.createFixture); return body; } @override Future onLoad() async { await super.onLoad(); renderBody = false; await add(_SpaceshipRampBackgroundRailingSpriteComponent()); await add(_SpaceshipRampBackgroundRampSpriteComponent()); } } class _SpaceshipRampBackgroundRailingSpriteComponent extends SpriteComponent with HasGameRef { @override Future onLoad() async { await super.onLoad(); final sprite = await gameRef.loadSprite( Assets.images.spaceship.ramp.railingBackground.keyName, ); this.sprite = sprite; size = Vector2(38.3, 35.1); anchor = Anchor.center; position = Vector2(-12.2, -54.5); } } class _SpaceshipRampBackgroundRampSpriteComponent extends SpriteComponent with HasGameRef { @override Future onLoad() async { await super.onLoad(); final sprite = await gameRef.loadSprite( Assets.images.spaceship.ramp.main.keyName, ); this.sprite = sprite; size = Vector2(38.3, 35.1); anchor = Anchor.center; position = Vector2(-12.2, -543.5); } } /// Represents the foreground of the railing upper left blue ramp. class _SpaceshipRampForegroundRailing extends BodyComponent with InitialPosition, Layered { _SpaceshipRampForegroundRailing() : super(priority: SpaceshipRamp.ballPriorityInsideRamp + 1) { layer = Layer.spaceshipEntranceRamp; } List _createFixtureDefs() { final fixturesDef = []; final innerLeftCurveShape = BezierCurveShape( controlPoints: [ Vector2(-24.5, 38), Vector2(-26.3, 64), Vector2(-13.8, 64.5), ], ); final innerLeftCurveFixtureDef = FixtureDef(innerLeftCurveShape); fixturesDef.add(innerLeftCurveFixtureDef); final innerRightCurveShape = BezierCurveShape( controlPoints: [ innerLeftCurveShape.vertices.last, Vector2(-1, 64.5), Vector2(0.1, 39.5), ], ); final innerRightCurveFixtureDef = FixtureDef(innerRightCurveShape); fixturesDef.add(innerRightCurveFixtureDef); return fixturesDef; } @override Body createBody() { renderBody = false; final bodyDef = BodyDef() ..userData = this ..position = initialPosition; final body = world.createBody(bodyDef); _createFixtureDefs().forEach(body.createFixture); return body; } @override Future onLoad() async { await super.onLoad(); await add(_SpaceshipRampForegroundRalingSpriteComponent()); } } class _SpaceshipRampForegroundRalingSpriteComponent extends SpriteComponent with HasGameRef { @override Future onLoad() async { await super.onLoad(); final sprite = await gameRef.loadSprite( Assets.images.spaceship.ramp.railingForeground.keyName, ); this.sprite = sprite; size = Vector2(26.1, 28.3); anchor = Anchor.center; position = Vector2(-12.2, -52.5); } } /// Represents the ground right base of the [SpaceshipRamp]. class _SpaceshipRampBase extends BodyComponent with InitialPosition, Layered { _SpaceshipRampBase() { layer = Layer.board; } @override Body createBody() { renderBody = false; const baseWidth = 6; final baseShape = BezierCurveShape( controlPoints: [ Vector2(initialPosition.x - baseWidth / 2, initialPosition.y), Vector2(initialPosition.x - baseWidth / 2, initialPosition.y) + Vector2(2, 2), Vector2(initialPosition.x + baseWidth / 2, initialPosition.y) + Vector2(-2, 2), Vector2(initialPosition.x + baseWidth / 2, initialPosition.y) ], ); final fixtureDef = FixtureDef(baseShape); final bodyDef = BodyDef() ..userData = this ..position = initialPosition; return world.createBody(bodyDef)..createFixture(fixtureDef); } } /// {@template spaceship_ramp_opening} /// [RampOpening] with [Layer.spaceshipEntranceRamp] to filter [Ball] collisions /// inside [_SpaceshipRampBackground]. /// {@endtemplate} class _SpaceshipRampOpening extends RampOpening { /// {@macro spaceship_ramp_opening} _SpaceshipRampOpening({ Layer? outsideLayer, int? outsidePriority, required double rotation, }) : _rotation = rotation, super( insideLayer: Layer.spaceshipEntranceRamp, outsideLayer: outsideLayer, orientation: RampOrientation.down, insidePriority: SpaceshipRamp.ballPriorityInsideRamp, outsidePriority: outsidePriority, ); final double _rotation; static final Vector2 _size = Vector2(_SpaceshipRampBackground.width / 4, .1); @override Shape get shape { renderBody = false; return PolygonShape() ..setAsBox( _size.x, _size.y, initialPosition, _rotation, ); } }