fix: flaky FireEffect test (#124)

* refactor: migrated to ParticleSystemComponent

* refactor: simplified tests

* feat: forced min count to be 1

* feat: adjusted priorities
pull/127/head
Alejandro Santiago 4 years ago committed by GitHub
parent e5c3708952
commit cbbf7b121e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -83,8 +83,9 @@ class Ball<T extends Forge2DGame> extends BodyComponent<T>
final direction = body.linearVelocity.normalized(); final direction = body.linearVelocity.normalized();
final effect = FireEffect( final effect = FireEffect(
burstPower: _boostTimer, burstPower: _boostTimer,
direction: direction, direction: -direction,
position: body.position, position: Vector2(body.position.x, -body.position.y),
priority: priority - 1,
); );
unawaited(gameRef.add(effect)); unawaited(gameRef.add(effect));

@ -1,5 +1,6 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame/extensions.dart'; import 'package:flame/extensions.dart';
import 'package:flame/particles.dart'; import 'package:flame/particles.dart';
import 'package:flame_forge2d/flame_forge2d.dart' hide Particle; import 'package:flame_forge2d/flame_forge2d.dart' hide Particle;
@ -19,33 +20,24 @@ const _particleRadius = 0.25;
/// A [BodyComponent] which creates a fire trail effect using the given /// A [BodyComponent] which creates a fire trail effect using the given
/// parameters /// parameters
/// {@endtemplate} /// {@endtemplate}
class FireEffect extends BodyComponent { class FireEffect extends ParticleSystemComponent {
/// {@macro fire_effect} /// {@macro fire_effect}
FireEffect({ FireEffect({
required this.burstPower, required this.burstPower,
required this.position,
required this.direction, required this.direction,
}); Vector2? position,
int? priority,
}) : super(
position: position,
priority: priority,
);
/// A [double] value that will define how "strong" the burst of particles /// A [double] value that will define how "strong" the burst of particles
/// will be /// will be.
final double burstPower; final double burstPower;
/// The position of the burst /// Which direction the burst will aim.
final Vector2 position;
/// Which direction the burst will aim
final Vector2 direction; final Vector2 direction;
late Particle _particle;
@override
Body createBody() {
final bodyDef = BodyDef()..position = position;
final fixtureDef = FixtureDef(CircleShape()..radius = 0)..isSensor = true;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
@ -71,15 +63,15 @@ class FireEffect extends BodyComponent {
); );
}), }),
]; ];
final rng = math.Random(); final random = math.Random();
final spreadTween = Tween<double>(begin: -0.2, end: 0.2); final spreadTween = Tween<double>(begin: -0.2, end: 0.2);
_particle = Particle.generate( particle = Particle.generate(
count: (rng.nextDouble() * (burstPower * 10)).toInt(), count: math.max((random.nextDouble() * (burstPower * 10)).toInt(), 1),
generator: (_) { generator: (_) {
final spread = Vector2( final spread = Vector2(
spreadTween.transform(rng.nextDouble()), spreadTween.transform(random.nextDouble()),
spreadTween.transform(rng.nextDouble()), spreadTween.transform(random.nextDouble()),
); );
final finalDirection = Vector2(direction.x, -direction.y) + spread; final finalDirection = Vector2(direction.x, -direction.y) + spread;
final speed = finalDirection * (burstPower * 20); final speed = finalDirection * (burstPower * 20);
@ -88,26 +80,9 @@ class FireEffect extends BodyComponent {
lifespan: 5 / burstPower, lifespan: 5 / burstPower,
position: Vector2.zero(), position: Vector2.zero(),
speed: speed, speed: speed,
child: children[rng.nextInt(children.length)], child: children[random.nextInt(children.length)],
); );
}, },
); );
} }
@override
void update(double dt) {
super.update(dt);
_particle.update(dt);
if (_particle.shouldRemove) {
removeFromParent();
}
}
@override
void render(Canvas canvas) {
super.render(canvas);
_particle.render(canvas);
}
} }

@ -34,7 +34,6 @@ class _EffectEmitter extends Component {
add( add(
FireEffect( FireEffect(
burstPower: (_timer / _timerLimit) * _force, burstPower: (_timer / _timerLimit) * _force,
position: Vector2.zero(),
direction: _direction, direction: _direction,
), ),
); );

@ -1,12 +1,8 @@
import 'dart:ui';
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:mocktail/mocktail.dart'; import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
class MockCanvas extends Mock implements Canvas {}
class MockFilter extends Mock implements Filter {} class MockFilter extends Mock implements Filter {}
class MockFixture extends Mock implements Fixture {} class MockFixture extends Mock implements Fixture {}

@ -1,11 +1,8 @@
// ignore_for_file: cascade_invocations // ignore_for_file: cascade_invocations
import 'dart:ui';
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_test/flame_test.dart'; import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
@ -14,43 +11,16 @@ void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new); final flameTester = FlameTester(TestGame.new);
setUpAll(() { flameTester.test(
registerFallbackValue(Offset.zero); 'loads correctly',
registerFallbackValue(Paint()); (game) async {
}); final fireEffect = FireEffect(
group('FireEffect', () {
flameTester.test('is removed once its particles are done', (game) async {
await game.ensureAdd(
FireEffect(
burstPower: 1, burstPower: 1,
position: Vector2.zero(), direction: Vector2.zero(),
direction: Vector2.all(2),
),
); );
await game.ready(); await game.ensureAdd(fireEffect);
expect(game.children.whereType<FireEffect>().length, equals(1));
game.update(5);
await game.ready();
expect(game.children.whereType<FireEffect>().length, equals(0));
});
flameTester.test('render circles on the canvas', (game) async {
final effect = FireEffect(
burstPower: 1,
position: Vector2.zero(),
direction: Vector2.all(2),
);
await game.ensureAdd(effect);
await game.ready();
final canvas = MockCanvas();
effect.render(canvas);
verify(() => canvas.drawCircle(any(), any(), any())).called( expect(game.contains(fireEffect), isTrue);
greaterThan(0), },
); );
});
});
} }

Loading…
Cancel
Save