feat: implemented `ScoreComponentScalingBehavior` (#391)

* feat: implemented ScoreComponentScalingBehavior

* fix: adjusted score ZIndex

* refactor: removed unused class

* refactor: adjusted goldens path
pull/358/head
Alejandro Santiago 3 years ago committed by alestiago
parent b3f891be0e
commit 42382f3b8a

@ -26,7 +26,7 @@ export 'multiball/multiball.dart';
export 'multiplier/multiplier.dart';
export 'plunger.dart';
export 'rocket.dart';
export 'score_component.dart';
export 'score_component/score_component.dart';
export 'shapes/shapes.dart';
export 'signpost/signpost.dart';
export 'skill_shot/skill_shot.dart';

@ -0,0 +1,24 @@
import 'package:flame/components.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
/// Scales a [ScoreComponent] according to its position on the board.
class ScoreComponentScalingBehavior extends Component
with ParentIsA<SpriteComponent> {
@override
void update(double dt) {
super.update(dt);
final boardHeight = BoardDimensions.bounds.height;
const maxShrinkValue = 0.83;
final augmentedPosition = parent.position.y * 3;
final standardizedYPosition = augmentedPosition + (boardHeight / 2);
final scaleFactor = maxShrinkValue +
((standardizedYPosition / boardHeight) * (1 - maxShrinkValue));
parent.scale.setValues(
scaleFactor,
scaleFactor,
);
}
}

@ -2,7 +2,9 @@ import 'dart:async';
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flutter/material.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/score_component/behaviors/score_component_scaling_behavior.dart';
import 'package:pinball_flame/pinball_flame.dart';
enum Points {
@ -26,10 +28,25 @@ class ScoreComponent extends SpriteComponent with HasGameRef, ZIndex {
super(
position: position,
anchor: Anchor.center,
children: [ScoreComponentScalingBehavior()],
) {
zIndex = ZIndexes.score;
}
/// Creates a [ScoreComponent] without any children.
///
/// This can be used for testing [ScoreComponent]'s behaviors in isolation.
@visibleForTesting
ScoreComponent.test({
required this.points,
required Vector2 position,
required EffectController effectController,
}) : _effectController = effectController,
super(
position: position,
anchor: Anchor.center,
);
late Points points;
late final Effect _effect;

@ -106,7 +106,7 @@ abstract class ZIndexes {
// Score
static const score = _above + spaceshipRampForegroundRailing;
static const score = _above + sparkyAnimatronic;
// Debug information

@ -10,8 +10,9 @@ import '../../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final asset = theme.Assets.images.dash.ball.keyName;
final flameTester = FlameTester(() => TestGame([asset]));
final flameTester = FlameTester(
() => TestGame([theme.Assets.images.dash.ball.keyName]),
);
group('BallScalingBehavior', () {
test('can be instantiated', () {

@ -0,0 +1,74 @@
// ignore_for_file: cascade_invocations
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/score_component/behaviors/behaviors.dart';
import '../../../../helpers/helpers.dart';
void main() {
group('ScoreComponentScalingBehavior', () {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(
() => TestGame([
Assets.images.score.fiveThousand.keyName,
Assets.images.score.twentyThousand.keyName,
Assets.images.score.twoHundredThousand.keyName,
Assets.images.score.oneMillion.keyName,
]),
);
test('can be instantiated', () {
expect(
ScoreComponentScalingBehavior(),
isA<ScoreComponentScalingBehavior>(),
);
});
flameTester.test('can be loaded', (game) async {
final parent = ScoreComponent.test(
points: Points.fiveThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
);
final behavior = ScoreComponentScalingBehavior();
await game.ensureAdd(parent);
await parent.ensureAdd(behavior);
expect(parent.children, contains(behavior));
});
flameTester.test(
'scales the sprite',
(game) async {
final parent1 = ScoreComponent.test(
points: Points.fiveThousand,
position: Vector2(0, 10),
effectController: EffectController(duration: 1),
);
final parent2 = ScoreComponent.test(
points: Points.fiveThousand,
position: Vector2(0, -10),
effectController: EffectController(duration: 1),
);
await game.ensureAddAll([parent1, parent2]);
await parent1.ensureAdd(ScoreComponentScalingBehavior());
await parent2.ensureAdd(ScoreComponentScalingBehavior());
game.update(1);
expect(
parent1.scale.x,
greaterThan(parent2.scale.x),
);
expect(
parent1.scale.y,
greaterThan(parent2.scale.y),
);
},
);
});
}

@ -5,24 +5,37 @@ import 'package:flame/effects.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/score_component/behaviors/behaviors.dart';
import '../../helpers/helpers.dart';
import '../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.score.fiveThousand.keyName,
Assets.images.score.twentyThousand.keyName,
Assets.images.score.twoHundredThousand.keyName,
Assets.images.score.oneMillion.keyName,
];
final flameTester = FlameTester(() => TestGame(assets));
final flameTester = FlameTester(
() => TestGame([
Assets.images.score.fiveThousand.keyName,
Assets.images.score.twentyThousand.keyName,
Assets.images.score.twoHundredThousand.keyName,
Assets.images.score.oneMillion.keyName,
]),
);
group('ScoreComponent', () {
test('can be instantiated', () {
expect(
ScoreComponent(
points: Points.fiveThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
),
isA<ScoreComponent>(),
);
});
flameTester.testGameWidget(
'loads correctly',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.onLoad();
game.camera.followVector2(Vector2.zero());
await game.ensureAdd(
ScoreComponent(
@ -38,13 +51,32 @@ void main() {
},
);
flameTester.test(
'adds a ScoreComponentScalingBehavior',
(game) async {
await game.onLoad();
game.camera.followVector2(Vector2.zero());
final component = ScoreComponent(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
);
await game.ensureAdd(component);
expect(
component.children.whereType<ScoreComponentScalingBehavior>().length,
equals(1),
);
},
);
flameTester.testGameWidget(
'has a movement effect',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.onLoad();
game.camera.followVector2(Vector2.zero());
await game.ensureAdd(
ScoreComponent(
ScoreComponent.test(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
@ -63,10 +95,10 @@ void main() {
flameTester.testGameWidget(
'is removed once finished',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.onLoad();
game.camera.followVector2(Vector2.zero());
await game.ensureAdd(
ScoreComponent(
ScoreComponent.test(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
@ -83,12 +115,14 @@ void main() {
);
group('renders correctly', () {
const goldensPath = '../golden/score/';
flameTester.testGameWidget(
'5000 points',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.onLoad();
await game.ensureAdd(
ScoreComponent(
ScoreComponent.test(
points: Points.fiveThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
@ -104,7 +138,7 @@ void main() {
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/score/5k.png'),
matchesGoldenFile('${goldensPath}5k.png'),
);
},
);
@ -112,9 +146,9 @@ void main() {
flameTester.testGameWidget(
'20000 points',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.onLoad();
await game.ensureAdd(
ScoreComponent(
ScoreComponent.test(
points: Points.twentyThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
@ -130,7 +164,7 @@ void main() {
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/score/20k.png'),
matchesGoldenFile('${goldensPath}20k.png'),
);
},
);
@ -138,9 +172,9 @@ void main() {
flameTester.testGameWidget(
'200000 points',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.onLoad();
await game.ensureAdd(
ScoreComponent(
ScoreComponent.test(
points: Points.twoHundredThousand,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
@ -156,7 +190,7 @@ void main() {
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/score/200k.png'),
matchesGoldenFile('${goldensPath}200k.png'),
);
},
);
@ -164,9 +198,9 @@ void main() {
flameTester.testGameWidget(
'1000000 points',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.onLoad();
await game.ensureAdd(
ScoreComponent(
ScoreComponent.test(
points: Points.oneMillion,
position: Vector2.zero(),
effectController: EffectController(duration: 1),
@ -182,7 +216,7 @@ void main() {
verify: (game, tester) async {
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/score/1m.png'),
matchesGoldenFile('${goldensPath}1m.png'),
);
},
);
Loading…
Cancel
Save