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 effect = FireEffect(
burstPower: _boostTimer,
direction: direction,
position: body.position,
direction: -direction,
position: Vector2(body.position.x, -body.position.y),
priority: priority - 1,
);
unawaited(gameRef.add(effect));

@ -1,5 +1,6 @@
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame/extensions.dart';
import 'package:flame/particles.dart';
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
/// parameters
/// {@endtemplate}
class FireEffect extends BodyComponent {
class FireEffect extends ParticleSystemComponent {
/// {@macro fire_effect}
FireEffect({
required this.burstPower,
required this.position,
required this.direction,
});
Vector2? position,
int? priority,
}) : super(
position: position,
priority: priority,
);
/// A [double] value that will define how "strong" the burst of particles
/// will be
/// will be.
final double burstPower;
/// The position of the burst
final Vector2 position;
/// Which direction the burst will aim
/// Which direction the burst will aim.
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
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);
_particle = Particle.generate(
count: (rng.nextDouble() * (burstPower * 10)).toInt(),
particle = Particle.generate(
count: math.max((random.nextDouble() * (burstPower * 10)).toInt(), 1),
generator: (_) {
final spread = Vector2(
spreadTween.transform(rng.nextDouble()),
spreadTween.transform(rng.nextDouble()),
spreadTween.transform(random.nextDouble()),
spreadTween.transform(random.nextDouble()),
);
final finalDirection = Vector2(direction.x, -direction.y) + spread;
final speed = finalDirection * (burstPower * 20);
@ -88,26 +80,9 @@ class FireEffect extends BodyComponent {
lifespan: 5 / burstPower,
position: Vector2.zero(),
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(
FireEffect(
burstPower: (_timer / _timerLimit) * _force,
position: Vector2.zero(),
direction: _direction,
),
);

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

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

Loading…
Cancel
Save