You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pinball/packages/pinball_components/lib/src/components/multiball/multiball.dart

139 lines
3.9 KiB

import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flutter/material.dart';
import 'package:pinball_components/gen/assets.gen.dart';
import 'package:pinball_components/src/components/multiball/behaviors/behaviors.dart';
import 'package:pinball_components/src/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
export 'cubit/multiball_cubit.dart';
/// {@template multiball}
/// A [Component] for the multiball lighting decals on the board.
/// {@endtemplate}
class Multiball extends Component {
/// {@macro multiball}
Multiball._({
required Vector2 position,
double rotation = 0,
Iterable<Component>? children,
required this.bloc,
}) : super(
children: [
MultiballBlinkingBehavior(),
MultiballSpriteGroupComponent(
position: position,
litAssetPath: Assets.images.multiball.lit.keyName,
dimmedAssetPath: Assets.images.multiball.dimmed.keyName,
rotation: rotation,
state: bloc.state.lightState,
),
...?children,
],
);
/// {@macro multiball}
Multiball.a({
Iterable<Component>? children,
}) : this._(
position: Vector2(-23, 7.5),
rotation: -24 * math.pi / 180,
bloc: MultiballCubit(),
children: children,
);
/// {@macro multiball}
Multiball.b({
Iterable<Component>? children,
}) : this._(
position: Vector2(-7.2, -6.2),
rotation: -5 * math.pi / 180,
bloc: MultiballCubit(),
children: children,
);
/// {@macro multiball}
Multiball.c({
Iterable<Component>? children,
}) : this._(
position: Vector2(-0.7, -9.3),
rotation: 2.7 * math.pi / 180,
bloc: MultiballCubit(),
children: children,
);
/// {@macro multiball}
Multiball.d({
Iterable<Component>? children,
}) : this._(
position: Vector2(15, 7),
rotation: 24 * math.pi / 180,
bloc: MultiballCubit(),
children: children,
);
/// Creates an [Multiball] without any children.
///
/// This can be used for testing [Multiball]'s behaviors in isolation.
// TODO(alestiago): Refactor injecting bloc once the following is merged:
// https://github.com/flame-engine/flame/pull/1538
@visibleForTesting
Multiball.test({
required this.bloc,
});
// TODO(alestiago): Consider refactoring once the following is merged:
// https://github.com/flame-engine/flame/pull/1538
// ignore: public_member_api_docs
final MultiballCubit bloc;
@override
void onRemove() {
bloc.close();
super.onRemove();
}
}
/// {@template multiball_sprite_group_component}
/// A [SpriteGroupComponent] for the multiball over the board.
/// {@endtemplate}
@visibleForTesting
class MultiballSpriteGroupComponent
extends SpriteGroupComponent<MultiballLightState>
with HasGameRef, ParentIsA<Multiball> {
/// {@macro multiball_sprite_group_component}
MultiballSpriteGroupComponent({
required Vector2 position,
required String litAssetPath,
required String dimmedAssetPath,
required double rotation,
required MultiballLightState state,
}) : _litAssetPath = litAssetPath,
_dimmedAssetPath = dimmedAssetPath,
super(
anchor: Anchor.center,
position: position,
angle: rotation,
current: state,
);
final String _litAssetPath;
final String _dimmedAssetPath;
@override
Future<void> onLoad() async {
await super.onLoad();
parent.bloc.stream.listen((state) => current = state.lightState);
final sprites = {
MultiballLightState.lit: Sprite(
gameRef.images.fromCache(_litAssetPath),
),
MultiballLightState.dimmed:
Sprite(gameRef.images.fromCache(_dimmedAssetPath)),
};
this.sprites = sprites;
size = sprites[current]!.originalSize / 10;
}
}