feat: defined ScoringBehavior

pull/329/head
alestiago 3 years ago
parent 6e42bea150
commit 9f0caa6079

@ -1,11 +1,55 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
/// {@template scoring_behavior}
/// Adds [_points] to the score and shows a text effect.
///
/// The behavior removes itself after the effect is completed.
/// {@endtemplate}
class ScoringBehavior extends Component with HasGameRef<PinballGame> {
/// {@macto scoring_behavior}
ScoringBehavior({
required Points points,
required Vector2 position,
double duration = 1,
}) : _points = points,
_position = position,
_effectController = EffectController(
duration: duration,
);
final Points _points;
final Vector2 _position;
final EffectController _effectController;
@override
void update(double dt) {
super.update(dt);
if (_effectController.completed) {
removeFromParent();
}
}
@override
Future<void> onLoad() async {
gameRef.read<GameBloc>().add(Scored(points: _points.value));
await gameRef.firstChild<ZCanvasComponent>()!.add(
ScoreComponent(
points: _points,
position: _position,
effectController: _effectController,
),
);
}
}
/// {@template scoring_contact_behavior}
/// Adds points to the score when the [Ball] contacts the [parent].
/// {@endtemplate}
@ -23,9 +67,8 @@ class ScoringContactBehavior extends ContactBehavior
super.beginContact(other, contact);
if (other is! Ball) return;
gameRef.read<GameBloc>().add(Scored(points: _points.value));
gameRef.firstChild<ZCanvasComponent>()!.add(
ScoreComponent(
parent.add(
ScoringBehavior(
points: _points,
position: other.body.position,
),

@ -23,16 +23,20 @@ class ScoreComponent extends SpriteComponent with HasGameRef, ZIndex {
ScoreComponent({
required this.points,
required Vector2 position,
}) : super(
required EffectController effectController,
}) : _effectController = effectController,
super(
position: position,
anchor: Anchor.center,
) {
zIndex = ZIndexes.score;
}
late Points points;
late final Effect _effect;
late Points points;
final EffectController _effectController;
@override
Future<void> onLoad() async {
@ -46,7 +50,7 @@ class ScoreComponent extends SpriteComponent with HasGameRef, ZIndex {
await add(
_effect = MoveEffect.by(
Vector2(0, -5),
EffectController(duration: 1),
_effectController,
),
);
}

@ -1,3 +1,4 @@
import 'package:flame/effects.dart';
import 'package:flame/input.dart';
import 'package:pinball_components/pinball_components.dart' as components;
import 'package:pinball_theme/pinball_theme.dart';
@ -52,6 +53,7 @@ class BackboardGameOverGame extends AssetsGame
points: components.Points.values
.firstWhere((element) => element.value == score),
position: Vector2(0, 50),
effectController: EffectController(duration: 1),
),
);
},

@ -1,5 +1,6 @@
import 'dart:math';
import 'package:flame/effects.dart';
import 'package:flame/input.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:sandbox/common/common.dart';
@ -38,6 +39,7 @@ class ScoreGame extends AssetsGame with TapDetector {
ScoreComponent(
points: score,
position: info.eventPosition.game..multiply(Vector2(1, -1)),
effectController: EffectController(duration: 1),
),
);
}

@ -28,6 +28,7 @@ void main() {
ScoreComponent(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
);
},
@ -46,6 +47,7 @@ void main() {
ScoreComponent(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
);
@ -67,6 +69,7 @@ void main() {
ScoreComponent(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
);
@ -88,6 +91,7 @@ void main() {
ScoreComponent(
points: Points.fiveThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
);
@ -113,6 +117,7 @@ void main() {
ScoreComponent(
points: Points.twentyThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
);
@ -138,6 +143,7 @@ void main() {
ScoreComponent(
points: Points.twoHundredThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
);
@ -163,6 +169,7 @@ void main() {
ScoreComponent(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
);

@ -34,8 +34,6 @@ void main() {
Assets.images.score.oneMillion.keyName,
];
group('ScoringContactBehavior', () {
group('beginContact', () {
late GameBloc bloc;
late Ball ball;
late BodyComponent parent;
@ -65,16 +63,47 @@ void main() {
assets: assets,
);
group('ScoringBehavior', () {
test('can be instantiated', () {
expect(
ScoringBehavior(
points: Points.fiveThousand,
position: Vector2.zero(),
),
isA<ScoringBehavior>(),
);
});
flameBlocTester.testGameWidget(
'emits Scored event with points',
'can be loaded',
setUp: (game, tester) async {
const points = Points.oneMillion;
final behavior = ScoringContactBehavior(points: points);
final canvas = ZCanvasComponent(children: [parent]);
final behavior = ScoringBehavior(
points: Points.fiveThousand,
position: Vector2.zero(),
);
await parent.add(behavior);
await game.ensureAdd(canvas);
expect(
parent.firstChild<ScoringBehavior>(),
equals(behavior),
);
},
);
flameBlocTester.testGameWidget(
'emits Scored event with points when added',
setUp: (game, tester) async {
const points = Points.oneMillion;
final canvas = ZCanvasComponent(children: [parent]);
await game.ensureAdd(canvas);
behavior.beginContact(ball, _MockContact());
final behavior = ScoringBehavior(
points: points,
position: Vector2(0, 0),
);
await parent.ensureAdd(behavior);
verify(
() => bloc.add(
@ -85,16 +114,18 @@ void main() {
);
flameBlocTester.testGameWidget(
"adds a ScoreComponent at Ball's position with points",
'correctly renders text',
setUp: (game, tester) async {
const points = Points.oneMillion;
final behavior = ScoringContactBehavior(points: points);
await parent.add(behavior);
final canvas = ZCanvasComponent(children: [parent]);
await game.ensureAdd(canvas);
behavior.beginContact(ball, _MockContact());
await game.ready();
const points = Points.oneMillion;
final position = Vector2.all(1);
final behavior = ScoringBehavior(
points: points,
position: position,
);
await parent.ensureAdd(behavior);
final scoreText = game.descendants().whereType<ScoreComponent>();
expect(scoreText.length, equals(1));
@ -104,10 +135,76 @@ void main() {
);
expect(
scoreText.first.position,
equals(ball.body.position),
equals(position),
);
},
);
flameBlocTester.testGameWidget(
'is removed after duration',
setUp: (game, tester) async {
final canvas = ZCanvasComponent(children: [parent]);
await game.ensureAdd(canvas);
const duration = 2.0;
final behavior = ScoringBehavior(
points: Points.oneMillion,
position: Vector2(0, 0),
duration: duration,
);
await parent.ensureAdd(behavior);
game.update(duration);
game.update(0);
await tester.pump();
},
verify: (game, _) async {
expect(
game.descendants().whereType<ScoringBehavior>(),
isEmpty,
);
},
);
});
group('ScoringContactBehavior', () {
flameBlocTester.testGameWidget(
'beginContact adds a ScoringBehavior',
setUp: (game, tester) async {
final canvas = ZCanvasComponent(children: [parent]);
await game.ensureAdd(canvas);
final behavior = ScoringContactBehavior(points: Points.oneMillion);
await parent.ensureAdd(behavior);
behavior.beginContact(ball, _MockContact());
await game.ready();
expect(
parent.firstChild<ScoringBehavior>(),
isNotNull,
);
},
);
flameBlocTester.testGameWidget(
"beginContact positions text at contact's position",
setUp: (game, tester) async {
final canvas = ZCanvasComponent(children: [parent]);
await game.ensureAdd(canvas);
final behavior = ScoringContactBehavior(points: Points.oneMillion);
await parent.ensureAdd(behavior);
behavior.beginContact(ball, _MockContact());
await game.ready();
final scoreText = game.descendants().whereType<ScoreComponent>();
expect(
scoreText.first.position,
equals(ball.body.position),
);
},
);
});
}

Loading…
Cancel
Save