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/ball/ball.dart

97 lines
2.8 KiB

import 'dart:async';
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/widgets.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
export 'behaviors/behaviors.dart';
/// {@template ball}
/// A solid, [BodyType.dynamic] sphere that rolls and bounces around.
/// {@endtemplate}
class Ball extends BodyComponent with Layered, InitialPosition, ZIndex {
/// {@macro ball}
Ball({
required this.baseColor,
}) : super(
renderBody: false,
children: [
_BallSpriteComponent()..tint(baseColor.withOpacity(0.5)),
BallScalingBehavior(),
BallGravitatingBehavior(),
],
) {
// TODO(ruimiguel): while developing Ball can be launched by clicking mouse,
// and default layer is Layer.all. But on final game Ball will be always be
// be launched from Plunger and LauncherRamp will modify it to Layer.board.
// We need to see what happens if Ball appears from other place like nest
// bumper, it will need to explicit change layer to Layer.board then.
layer = Layer.board;
}
/// Creates a [Ball] without any behaviors.
///
/// This can be used for testing [Ball]'s behaviors in isolation.
@visibleForTesting
Ball.test({required this.baseColor})
: super(
children: [_BallSpriteComponent()],
);
/// The size of the [Ball].
static final Vector2 size = Vector2.all(4.13);
/// The base [Color] used to tint this [Ball].
final Color baseColor;
@override
Body createBody() {
final shape = CircleShape()..radius = size.x / 2;
final fixtureDef = FixtureDef(
shape,
density: 1,
);
final bodyDef = BodyDef(
position: initialPosition,
userData: this,
type: BodyType.dynamic,
);
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
/// Immediatly and completly [stop]s the ball.
///
/// The [Ball] will no longer be affected by any forces, including it's
/// weight and those emitted from collisions.
// TODO(allisonryan0002): prevent motion from contact with other balls.
void stop() {
body
..gravityScale = Vector2.zero()
..linearVelocity = Vector2.zero()
..angularVelocity = 0;
}
/// Allows the [Ball] to be affected by forces.
///
/// If previously [stop]ped, the previous ball's velocity is not kept.
void resume() {
body.gravityScale = Vector2(1, 1);
}
}
class _BallSpriteComponent extends SpriteComponent with HasGameRef {
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(
Assets.images.ball.ball.keyName,
);
this.sprite = sprite;
size = sprite.originalSize / 10;
anchor = Anchor.center;
}
}