mirror of https://github.com/flutter/pinball.git
refactor: moved boost logic to `BallTurboChargingBehavior` (#323)
* feat(pinball_components): defined BallTurboChargingBehavior * feat: updated boosting logic * docs: improved BallTurboChargingBehavior * docs(pinball_components): changed verb * test: removed empty group * test: included instantiation and loading testspull/328/head
parent
b0f6709828
commit
44566bcbf0
@ -0,0 +1,81 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
/// {@template ball_turbo_charging_behavior}
|
||||
/// Puts the [Ball] in flames and [_impulse]s it.
|
||||
/// {@endtemplate}
|
||||
class BallTurboChargingBehavior extends TimerComponent with ParentIsA<Ball> {
|
||||
/// {@macro ball_turbo_charging_behavior}
|
||||
BallTurboChargingBehavior({
|
||||
required Vector2 impulse,
|
||||
}) : _impulse = impulse,
|
||||
super(period: 5, removeOnFinish: true);
|
||||
|
||||
final Vector2 _impulse;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
parent.body.linearVelocity = _impulse;
|
||||
await parent.add(_TurboChargeSpriteAnimationComponent());
|
||||
}
|
||||
|
||||
@override
|
||||
void onRemove() {
|
||||
parent
|
||||
.firstChild<_TurboChargeSpriteAnimationComponent>()!
|
||||
.removeFromParent();
|
||||
super.onRemove();
|
||||
}
|
||||
}
|
||||
|
||||
class _TurboChargeSpriteAnimationComponent extends SpriteAnimationComponent
|
||||
with HasGameRef, ZIndex, ParentIsA<Ball> {
|
||||
_TurboChargeSpriteAnimationComponent()
|
||||
: super(
|
||||
anchor: const Anchor(0.53, 0.72),
|
||||
) {
|
||||
zIndex = ZIndexes.turboChargeFlame;
|
||||
}
|
||||
|
||||
late final Vector2 _textureSize;
|
||||
|
||||
@override
|
||||
void update(double dt) {
|
||||
super.update(dt);
|
||||
|
||||
final direction = -parent.body.linearVelocity.normalized();
|
||||
angle = math.atan2(direction.x, -direction.y);
|
||||
size = (_textureSize / 45) * parent.body.fixtures.first.shape.radius;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
final spriteSheet = await gameRef.images.load(
|
||||
Assets.images.ball.flameEffect.keyName,
|
||||
);
|
||||
|
||||
const amountPerRow = 8;
|
||||
const amountPerColumn = 4;
|
||||
_textureSize = Vector2(
|
||||
spriteSheet.width / amountPerRow,
|
||||
spriteSheet.height / amountPerColumn,
|
||||
);
|
||||
|
||||
animation = SpriteAnimation.fromFrameData(
|
||||
spriteSheet,
|
||||
SpriteAnimationData.sequenced(
|
||||
amount: amountPerRow * amountPerColumn,
|
||||
amountPerRow: amountPerRow,
|
||||
stepTime: 1 / 24,
|
||||
textureSize: _textureSize,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
export 'ball_gravitating_behavior.dart';
|
||||
export 'ball_scaling_behavior.dart';
|
||||
export 'ball_turbo_charging_behavior.dart';
|
||||
|
@ -0,0 +1,94 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
import '../../../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group(
|
||||
'BallTurboChargingBehavior',
|
||||
() {
|
||||
final assets = [Assets.images.ball.ball.keyName];
|
||||
final flameTester = FlameTester(() => TestGame(assets));
|
||||
const baseColor = Color(0xFFFFFFFF);
|
||||
|
||||
test('can be instantiated', () {
|
||||
expect(
|
||||
BallTurboChargingBehavior(impulse: Vector2.zero()),
|
||||
isA<BallTurboChargingBehavior>(),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('can be loaded', (game) async {
|
||||
final ball = Ball.test(baseColor: baseColor);
|
||||
final behavior = BallTurboChargingBehavior(impulse: Vector2.zero());
|
||||
await ball.add(behavior);
|
||||
await game.ensureAdd(ball);
|
||||
expect(
|
||||
ball.firstChild<BallTurboChargingBehavior>(),
|
||||
equals(behavior),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test(
|
||||
'impulses the ball velocity when loaded',
|
||||
(game) async {
|
||||
final ball = Ball.test(baseColor: baseColor);
|
||||
await game.ensureAdd(ball);
|
||||
final impulse = Vector2.all(1);
|
||||
final behavior = BallTurboChargingBehavior(impulse: impulse);
|
||||
await ball.ensureAdd(behavior);
|
||||
|
||||
expect(
|
||||
ball.body.linearVelocity.x,
|
||||
equals(impulse.x),
|
||||
);
|
||||
expect(
|
||||
ball.body.linearVelocity.y,
|
||||
equals(impulse.y),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test('adds sprite', (game) async {
|
||||
final ball = Ball(baseColor: baseColor);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
await ball.ensureAdd(
|
||||
BallTurboChargingBehavior(impulse: Vector2.zero()),
|
||||
);
|
||||
|
||||
expect(
|
||||
ball.children.whereType<SpriteAnimationComponent>().single,
|
||||
isNotNull,
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('removes sprite after it finishes', (game) async {
|
||||
final ball = Ball(baseColor: baseColor);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
final behavior = BallTurboChargingBehavior(impulse: Vector2.zero());
|
||||
await ball.ensureAdd(behavior);
|
||||
|
||||
final turboChargeSpriteAnimation =
|
||||
ball.children.whereType<SpriteAnimationComponent>().single;
|
||||
|
||||
expect(ball.contains(turboChargeSpriteAnimation), isTrue);
|
||||
|
||||
game.update(behavior.timer.limit);
|
||||
game.update(0.1);
|
||||
|
||||
expect(ball.contains(turboChargeSpriteAnimation), isFalse);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
Loading…
Reference in new issue