mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Optimizations to particle systems. Uses single instance of Random and faster atan2 function.
This commit is contained in:
parent
f3e51d9f05
commit
53c66a5f4c
@ -80,8 +80,6 @@ class ParticleSystem extends Node {
|
||||
// double _elapsedTime;
|
||||
int _numEmittedParticles = 0;
|
||||
|
||||
math.Random _rand;
|
||||
|
||||
ParticleSystem(this.texture,
|
||||
{this.life: 1.5,
|
||||
this.lifeVar: 1.0,
|
||||
@ -116,7 +114,6 @@ class ParticleSystem extends Node {
|
||||
this.numParticlesToEmit: 0,
|
||||
this.autoRemoveOnFinish: true}) {
|
||||
_particles = new List<_Particle>();
|
||||
_rand = new math.Random();
|
||||
_emitCounter = 0.0;
|
||||
// _elapsedTime = 0.0;
|
||||
if (gravity == null) gravity = new Vector2.zero();
|
||||
@ -124,6 +121,8 @@ class ParticleSystem extends Node {
|
||||
}
|
||||
|
||||
void update(double dt) {
|
||||
// TODO: Fix this (it's a temp fix for low framerates)
|
||||
if (dt > 0.1) dt = 0.1;
|
||||
|
||||
// Create new particles
|
||||
double rate = 1.0 / emissionRate;
|
||||
@ -196,34 +195,34 @@ class ParticleSystem extends Node {
|
||||
_Particle particle = new _Particle();
|
||||
|
||||
// Time to live
|
||||
particle.timeToLive = math.max(life + lifeVar * randMinus1To1(), 0.0);
|
||||
particle.timeToLive = math.max(life + lifeVar * randomSignedDouble(), 0.0);
|
||||
|
||||
// Position
|
||||
Point srcPos = Point.origin;
|
||||
particle.pos = new Vector2(srcPos.x + posVar.x * randMinus1To1(),
|
||||
srcPos.y + posVar.y * randMinus1To1());
|
||||
particle.pos = new Vector2(srcPos.x + posVar.x * randomSignedDouble(),
|
||||
srcPos.y + posVar.y * randomSignedDouble());
|
||||
|
||||
// Size
|
||||
particle.size = math.max(startSize + startSizeVar * randMinus1To1(), 0.0);
|
||||
double endSizeFinal = math.max(endSize + endSizeVar * randMinus1To1(), 0.0);
|
||||
particle.size = math.max(startSize + startSizeVar * randomSignedDouble(), 0.0);
|
||||
double endSizeFinal = math.max(endSize + endSizeVar * randomSignedDouble(), 0.0);
|
||||
particle.deltaSize = (endSizeFinal - particle.size) / particle.timeToLive;
|
||||
|
||||
// Rotation
|
||||
particle.rotation = startRotation + startRotationVar * randMinus1To1();
|
||||
double endRotationFinal = endRotation + endRotationVar * randMinus1To1();
|
||||
particle.rotation = startRotation + startRotationVar * randomSignedDouble();
|
||||
double endRotationFinal = endRotation + endRotationVar * randomSignedDouble();
|
||||
particle.deltaRotation = (endRotationFinal - particle.rotation) / particle.timeToLive;
|
||||
|
||||
// Direction
|
||||
double dirRadians = convertDegrees2Radians(direction + directionVar * randMinus1To1());
|
||||
double dirRadians = convertDegrees2Radians(direction + directionVar * randomSignedDouble());
|
||||
Vector2 dirVector = new Vector2(math.cos(dirRadians), math.sin(dirRadians));
|
||||
double speedFinal = speed + speedVar * randMinus1To1();
|
||||
double speedFinal = speed + speedVar * randomSignedDouble();
|
||||
particle.dir = dirVector.scale(speedFinal);
|
||||
|
||||
// Radial acceleration
|
||||
particle.radialAccel = radialAcceleration + radialAccelerationVar * randMinus1To1();
|
||||
particle.radialAccel = radialAcceleration + radialAccelerationVar * randomSignedDouble();
|
||||
|
||||
// Tangential acceleration
|
||||
particle.tangentialAccel = tangentialAcceleration + tangentialAccelerationVar * randMinus1To1();
|
||||
particle.tangentialAccel = tangentialAcceleration + tangentialAccelerationVar * randomSignedDouble();
|
||||
|
||||
// Color
|
||||
particle.colorPos = 0.0;
|
||||
@ -248,7 +247,7 @@ class ParticleSystem extends Node {
|
||||
double scos;
|
||||
double ssin;
|
||||
if (rotateToMovement) {
|
||||
double extraRotation = math.atan2(particle.dir[1], particle.dir[0]);
|
||||
double extraRotation = GameMath.atan2(particle.dir[1], particle.dir[0]);
|
||||
scos = math.cos(convertDegrees2Radians(particle.rotation) + extraRotation) * particle.size;
|
||||
ssin = math.sin(convertDegrees2Radians(particle.rotation) + extraRotation) * particle.size;
|
||||
} else {
|
||||
@ -276,14 +275,12 @@ class ParticleSystem extends Node {
|
||||
Paint paint = new Paint()..setTransferMode(transferMode)
|
||||
..setFilterQuality(FilterQuality.low) // All Skia examples do this.
|
||||
..isAntiAlias = false; // Antialiasing breaks SkCanvas.drawAtlas?
|
||||
// return canvas.drawAtlas(texture.image, transforms, rects, colors,
|
||||
// TransferMode.modulate, null, paint);
|
||||
return canvas.drawAtlas(texture.image, transforms, rects, colors,
|
||||
TransferMode.modulate, null, paint);
|
||||
|
||||
dartDrawAtlas(canvas, texture.image, transforms, rects, colors,
|
||||
TransferMode.modulate, paint);
|
||||
}
|
||||
|
||||
double randMinus1To1() => _rand.nextDouble() * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
void dartDrawAtlas(Canvas canvas, Image image, List<RSTransform> transforms,
|
||||
|
||||
@ -1,2 +1,86 @@
|
||||
part of sprites;
|
||||
|
||||
|
||||
math.Random _random = new math.Random();
|
||||
|
||||
// Random methods
|
||||
|
||||
double randomDouble() {
|
||||
return _random.nextDouble();
|
||||
}
|
||||
|
||||
double randomSignedDouble() {
|
||||
return _random.nextDouble() * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
int randomInt(int max) {
|
||||
return _random.nextInt(max);
|
||||
}
|
||||
|
||||
// atan2
|
||||
|
||||
class GameMath {
|
||||
static bool _inited = false;
|
||||
|
||||
static final int size = 1024;
|
||||
static final double stretch = math.PI;
|
||||
|
||||
static final int ezis = -size;
|
||||
|
||||
static Float64List atan2_table_ppy = new Float64List(size + 1);
|
||||
static Float64List atan2_table_ppx = new Float64List(size + 1);
|
||||
static Float64List atan2_table_pny = new Float64List(size + 1);
|
||||
static Float64List atan2_table_pnx = new Float64List(size + 1);
|
||||
static Float64List atan2_table_npy = new Float64List(size + 1);
|
||||
static Float64List atan2_table_npx = new Float64List(size + 1);
|
||||
static Float64List atan2_table_nny = new Float64List(size + 1);
|
||||
static Float64List atan2_table_nnx = new Float64List(size + 1);
|
||||
|
||||
static void init() {
|
||||
if (_inited) return;
|
||||
|
||||
for (int i = 0; i <= size; i++) {
|
||||
double f = i.toDouble() / size.toDouble();
|
||||
atan2_table_ppy[i] = math.atan(f) * stretch / math.PI;
|
||||
atan2_table_ppx[i] = stretch * 0.5 - atan2_table_ppy[i];
|
||||
atan2_table_pny[i] = -atan2_table_ppy[i];
|
||||
atan2_table_pnx[i] = atan2_table_ppy[i] - stretch * 0.5;
|
||||
atan2_table_npy[i] = stretch - atan2_table_ppy[i];
|
||||
atan2_table_npx[i] = atan2_table_ppy[i] + stretch * 0.5;
|
||||
atan2_table_nny[i] = atan2_table_ppy[i] - stretch;
|
||||
atan2_table_nnx[i] = -stretch * 0.5 - atan2_table_ppy[i];
|
||||
}
|
||||
_inited = true;
|
||||
}
|
||||
|
||||
static double atan2(double y, double x) {
|
||||
if (!_inited)
|
||||
init();
|
||||
|
||||
if (x >= 0) {
|
||||
if (y >= 0) {
|
||||
if (x >= y)
|
||||
return atan2_table_ppy[(size * y / x + 0.5).toInt()];
|
||||
else
|
||||
return atan2_table_ppx[(size * x / y + 0.5).toInt()];
|
||||
} else {
|
||||
if (x >= -y)
|
||||
return atan2_table_pny[(ezis * y / x + 0.5).toInt()];
|
||||
else
|
||||
return atan2_table_pnx[(ezis * x / y + 0.5).toInt()];
|
||||
}
|
||||
} else {
|
||||
if (y >= 0) {
|
||||
if (-x >= y)
|
||||
return atan2_table_npy[(ezis * y / x + 0.5).toInt()];
|
||||
else
|
||||
return atan2_table_npx[(ezis * x / y + 0.5).toInt()];
|
||||
} else {
|
||||
if (x <= y)
|
||||
return atan2_table_nny[(size * y / x + 0.5).toInt()];
|
||||
else
|
||||
return atan2_table_nnx[(size * x / y + 0.5).toInt()];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user