mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
Merge pull request #273 from vlidholt/master
Optimizations for Particle Systems
This commit is contained in:
commit
80f8435916
|
@ -24,13 +24,11 @@ class ColorSequence {
|
|||
colors = new List<Color>();
|
||||
colorStops = new List<double>.from(sequence.colorStops);
|
||||
|
||||
math.Random rand = new math.Random();
|
||||
|
||||
for (Color color in sequence.colors) {
|
||||
int aDelta = ((rand.nextDouble() * 2.0 - 1.0) * alphaVar).toInt();
|
||||
int rDelta = ((rand.nextDouble() * 2.0 - 1.0) * redVar).toInt();
|
||||
int gDelta = ((rand.nextDouble() * 2.0 - 1.0) * greenVar).toInt();
|
||||
int bDelta = ((rand.nextDouble() * 2.0 - 1.0) * blueVar).toInt();
|
||||
int aDelta = ((randomDouble() * 2.0 - 1.0) * alphaVar).toInt();
|
||||
int rDelta = ((randomDouble() * 2.0 - 1.0) * redVar).toInt();
|
||||
int gDelta = ((randomDouble() * 2.0 - 1.0) * greenVar).toInt();
|
||||
int bDelta = ((randomDouble() * 2.0 - 1.0) * blueVar).toInt();
|
||||
|
||||
int aNew = (color.alpha + aDelta).clamp(0, 255);
|
||||
int rNew = (color.red + rDelta).clamp(0, 255);
|
||||
|
|
|
@ -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 {
|
||||
|
@ -275,10 +274,7 @@ 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,
|
||||
canvas.drawAtlas(texture.image, transforms, rects, colors,
|
||||
TransferMode.modulate, null, paint);
|
||||
}
|
||||
|
||||
double randMinus1To1() => _rand.nextDouble() * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ library sprites;
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:typed_data';
|
||||
import 'dart:sky';
|
||||
|
||||
import 'package:sky/animation/curves.dart';
|
||||
|
|
|
@ -1,2 +1,83 @@
|
|||
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 _Atan2Constants {
|
||||
|
||||
_Atan2Constants() {
|
||||
for (int i = 0; i <= size; i++) {
|
||||
double f = i.toDouble() / size.toDouble();
|
||||
ppy[i] = math.atan(f) * stretch / math.PI;
|
||||
ppx[i] = stretch * 0.5 - ppy[i];
|
||||
pny[i] = -ppy[i];
|
||||
pnx[i] = ppy[i] - stretch * 0.5;
|
||||
npy[i] = stretch - ppy[i];
|
||||
npx[i] = ppy[i] + stretch * 0.5;
|
||||
nny[i] = ppy[i] - stretch;
|
||||
nnx[i] = -stretch * 0.5 - ppy[i];
|
||||
}
|
||||
}
|
||||
|
||||
static const int size = 1024;
|
||||
static const double stretch = math.PI;
|
||||
|
||||
static const int ezis = -size;
|
||||
|
||||
final Float64List ppy = new Float64List(size + 1);
|
||||
final Float64List ppx = new Float64List(size + 1);
|
||||
final Float64List pny = new Float64List(size + 1);
|
||||
final Float64List pnx = new Float64List(size + 1);
|
||||
final Float64List npy = new Float64List(size + 1);
|
||||
final Float64List npx = new Float64List(size + 1);
|
||||
final Float64List nny = new Float64List(size + 1);
|
||||
final Float64List nnx = new Float64List(size + 1);
|
||||
}
|
||||
|
||||
class GameMath {
|
||||
static final _Atan2Constants _atan2 = new _Atan2Constants();
|
||||
|
||||
static double atan2(double y, double x) {
|
||||
if (x >= 0) {
|
||||
if (y >= 0) {
|
||||
if (x >= y)
|
||||
return _atan2.ppy[(_Atan2Constants.size * y / x + 0.5).floor()];
|
||||
else
|
||||
return _atan2.ppx[(_Atan2Constants.size * x / y + 0.5).floor()];
|
||||
} else {
|
||||
if (x >= -y)
|
||||
return _atan2.pny[(_Atan2Constants.ezis * y / x + 0.5).floor()];
|
||||
else
|
||||
return _atan2.pnx[(_Atan2Constants.ezis * x / y + 0.5).floor()];
|
||||
}
|
||||
} else {
|
||||
if (y >= 0) {
|
||||
if (-x >= y)
|
||||
return _atan2.npy[(_Atan2Constants.ezis * y / x + 0.5).floor()];
|
||||
else
|
||||
return _atan2.npx[(_Atan2Constants.ezis * x / y + 0.5).floor()];
|
||||
} else {
|
||||
if (x <= y)
|
||||
return _atan2.nny[(_Atan2Constants.size * y / x + 0.5).floor()];
|
||||
else
|
||||
return _atan2.nnx[(_Atan2Constants.size * x / y + 0.5).floor()];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue