Skip to content

Commit

Permalink
feat: Scaling particle feature (#2830)
Browse files Browse the repository at this point in the history
Added a ScalingParticle class that lerp between 1 and a given scale, a
shorthand in the Particle class called scaling and updated the docs.
Also exposed a getter for the lifespan property in the Particle class.
  • Loading branch information
brenoasm committed Oct 29, 2023
1 parent 3a8e246 commit 9faae8a
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
20 changes: 20 additions & 0 deletions doc/flame/rendering/particles.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,26 @@ game.add(
```


## ScalingParticle

Scales the child `Particle` between `1` and `to` during its lifespan.

```dart
game.add(
ParticleSystemComponent(
particle: ScalingParticle(
lifespan: 2,
to: 0,
child: CircleParticle(
radius: 2.0,
paint: Paint()..color = Colors.red,
)
);
),
);
```


## SpriteAnimationParticle

A `Particle` which embeds a `SpriteAnimation`.
Expand Down
11 changes: 11 additions & 0 deletions packages/flame/lib/src/particles/particle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:flame/src/particles/composed_particle.dart';
import 'package:flame/src/particles/moving_particle.dart';
import 'package:flame/src/particles/rotating_particle.dart';
import 'package:flame/src/particles/scaled_particle.dart';
import 'package:flame/src/particles/scaling_particle.dart';
import 'package:flame/src/particles/translated_particle.dart';
import 'package:flame/src/timer.dart';
import 'package:flutter/animation.dart';
Expand Down Expand Up @@ -59,6 +60,9 @@ abstract class Particle {
setLifespan(lifespan ?? .5);
}

/// Getter for the current lifespan of this [Particle].
double get lifespan => _lifespan;

/// This method will return true as soon as the particle reaches the end of
/// its lifespan.
///
Expand Down Expand Up @@ -173,4 +177,11 @@ abstract class Particle {
Particle scaled(double scale) {
return ScaledParticle(scale: scale, child: this, lifespan: _lifespan);
}

/// Wraps this particle with a [ScalingParticle].
///
/// Allows for changing the size of this particle and/or its children.
ScalingParticle scaling({double to = 0}) {
return ScalingParticle(to: to, child: this, lifespan: _lifespan);
}
}
30 changes: 30 additions & 0 deletions packages/flame/lib/src/particles/scaling_particle.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'dart:ui';

import 'package:flame/src/components/mixins/single_child_particle.dart';
import 'package:flame/src/particles/curved_particle.dart';
import 'package:flame/src/particles/particle.dart';

/// A particle which scale its child over the lifespan
/// between 1 and a provided scale.
class ScalingParticle extends CurvedParticle with SingleChildParticle {
@override
Particle child;

final double to;

ScalingParticle({
required this.child,
this.to = 0,
super.lifespan,
});

double get scale => lerpDouble(1, to, progress) ?? 0;

@override
void render(Canvas canvas) {
canvas.save();
canvas.scale(scale);
super.render(canvas);
canvas.restore();
}
}
36 changes: 36 additions & 0 deletions packages/flame/test/particles/scaling_particle_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:flame/src/components/particle_system_component.dart';
import 'package:flame/src/particles/computed_particle.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
group('ScalingParticle', () {
testWithFlameGame(
'A particle which scale its child over the lifespan '
'between 1 and a provided scale', (game) async {
final paint = Paint()..color = Colors.red;
final rect = ComputedParticle(
lifespan: 2,
renderer: (canvas, _) => canvas.drawRect(
Rect.fromCenter(center: Offset.zero, width: 10, height: 10),
paint,
),
);

final particle = rect.scaling(to: .5);

final component = ParticleSystemComponent(
particle: particle,
);

game.add(component);
await game.ready();
game.update(1);

expect(particle.scale, .75);
expect(particle.child, isInstanceOf<ComputedParticle>());
expect(particle.child.progress, 0.5);
});
});
}

0 comments on commit 9faae8a

Please sign in to comment.