diff --git a/packages/pinball_components/lib/src/components/components.dart b/packages/pinball_components/lib/src/components/components.dart index 4e38c2c4..bbb2c29c 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 'dash_nest_bumper.dart'; export 'dino_walls.dart'; export 'fire_effect.dart'; export 'flipper.dart'; diff --git a/packages/pinball_components/lib/src/components/dash_nest_bumper.dart b/packages/pinball_components/lib/src/components/dash_nest_bumper.dart new file mode 100644 index 00000000..a2b9b982 --- /dev/null +++ b/packages/pinball_components/lib/src/components/dash_nest_bumper.dart @@ -0,0 +1,142 @@ +import 'dart:math' as math; + +import 'package:flame/components.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:pinball_components/pinball_components.dart'; + +/// {@template dash_nest_bumper} +/// Bumper with a nest appearance. +/// {@endtemplate} +abstract class DashNestBumper extends BodyComponent with InitialPosition { + /// {@macro dash_nest_bumper} + DashNestBumper._({ + required String activeAssetPath, + required String inactiveAssetPath, + required SpriteComponent spriteComponent, + }) : _activeAssetPath = activeAssetPath, + _inactiveAssetPath = inactiveAssetPath, + _spriteComponent = spriteComponent; + + final String _activeAssetPath; + late final Sprite _activeSprite; + final String _inactiveAssetPath; + late final Sprite _inactiveSprite; + final SpriteComponent _spriteComponent; + + Future _loadSprites() async { + // TODO(alestiago): I think ideally we would like to do: + // Sprite(path).load so we don't require to store the activeAssetPath and + // the inactive assetPath. + _inactiveSprite = await gameRef.loadSprite(_inactiveAssetPath); + _activeSprite = await gameRef.loadSprite(_activeAssetPath); + } + + /// Activates the [DashNestBumper]. + void activate() { + _spriteComponent + ..sprite = _activeSprite + ..size = _activeSprite.originalSize / 10; + } + + /// Deactivates the [DashNestBumper]. + void deactivate() { + _spriteComponent + ..sprite = _inactiveSprite + ..size = _inactiveSprite.originalSize / 10; + } + + @override + Future onLoad() async { + await super.onLoad(); + await _loadSprites(); + + // TODO(erickzanardo): Look into using onNewState instead. + // Currently doing: onNewState(gameRef.read()) will throw an + // `Exception: build context is not available yet` + deactivate(); + await add(_spriteComponent); + } +} + +/// {@macro dash_nest_bumper} +class BigDashNestBumper extends DashNestBumper { + /// {@macro dash_nest_bumper} + BigDashNestBumper() + : super._( + activeAssetPath: Assets.images.dashBumper.main.active.keyName, + inactiveAssetPath: Assets.images.dashBumper.main.inactive.keyName, + spriteComponent: SpriteComponent( + anchor: Anchor.center, + ), + ); + + @override + Body createBody() { + final shape = EllipseShape( + center: Vector2.zero(), + majorRadius: 4.85, + minorRadius: 3.95, + )..rotate(math.pi / 2); + final fixtureDef = FixtureDef(shape); + + final bodyDef = BodyDef() + ..position = initialPosition + ..userData = this; + + return world.createBody(bodyDef)..createFixture(fixtureDef); + } +} + +/// {@macro dash_nest_bumper} +class SmallDashNestBumper extends DashNestBumper { + /// {@macro dash_nest_bumper} + SmallDashNestBumper._({ + required String activeAssetPath, + required String inactiveAssetPath, + required SpriteComponent spriteComponent, + }) : super._( + activeAssetPath: activeAssetPath, + inactiveAssetPath: inactiveAssetPath, + spriteComponent: spriteComponent, + ); + + /// {@macro dash_nest_bumper} + SmallDashNestBumper.a() + : this._( + activeAssetPath: Assets.images.dashBumper.a.active.keyName, + inactiveAssetPath: Assets.images.dashBumper.a.inactive.keyName, + spriteComponent: SpriteComponent( + anchor: Anchor.center, + position: Vector2(0.35, -1.2), + ), + ); + + /// {@macro dash_nest_bumper} + SmallDashNestBumper.b() + : this._( + activeAssetPath: Assets.images.dashBumper.b.active.keyName, + inactiveAssetPath: Assets.images.dashBumper.b.inactive.keyName, + spriteComponent: SpriteComponent( + anchor: Anchor.center, + position: Vector2(0.35, -1.2), + ), + ); + + @override + Body createBody() { + final shape = EllipseShape( + center: Vector2.zero(), + majorRadius: 3, + minorRadius: 2.25, + )..rotate(math.pi / 2); + final fixtureDef = FixtureDef(shape) + ..friction = 0 + ..restitution = 4; + + final bodyDef = BodyDef() + ..position = initialPosition + ..userData = this; + + return world.createBody(bodyDef)..createFixture(fixtureDef); + } +}