提交 80920302 编写于 作者: V Viktor Lidholt

Refactors randomizations of color sequences and optimizes particle systems...

Refactors randomizations of color sequences and optimizes particle systems (uses single Paint instance, doesn't compute accelerations unless used, reduces number of created objects, faster color calculations)
Fixes indentation
Optimizes lookup in fast version of atan2 (toInt is faster than floor)
Removes frame rate printout and adds assert
上级 6a8e4898
......@@ -20,25 +20,6 @@ class ColorSequence {
colorStops = new List<double>.from(sequence.colorStops);
}
ColorSequence.copyWithVariance(ColorSequence sequence, int alphaVar, int redVar, int greenVar, int blueVar) {
colors = new List<Color>();
colorStops = new List<double>.from(sequence.colorStops);
for (Color color in sequence.colors) {
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);
int gNew = (color.green + gDelta).clamp(0, 255);
int bNew = (color.blue + bDelta).clamp(0, 255);
colors.add(new Color.fromARGB(aNew, rNew, gNew, bNew));
}
}
Color colorAtPosition(double pos) {
assert(pos >= 0.0 && pos <= 1.0);
......
......@@ -16,12 +16,18 @@ class _Particle {
double timeToLive;
Vector2 dir;
double radialAccel;
double tangentialAccel;
_ParticleAccelerations accelerations;
Float64List simpleColorSequence;
ColorSequence colorSequence;
}
class _ParticleAccelerations {
double radialAccel;
double tangentialAccel;
}
class ParticleSystem extends Node {
......@@ -76,10 +82,12 @@ class ParticleSystem extends Node {
List<_Particle> _particles;
double _emitCounter;
// Not yet used:
// double _elapsedTime;
int _numEmittedParticles = 0;
static Paint _paint = new Paint()
..setFilterQuality(FilterQuality.low)
..isAntiAlias = false;
ParticleSystem(this.texture,
{this.life: 1.5,
this.lifeVar: 1.0,
......@@ -154,26 +162,35 @@ class ParticleSystem extends Node {
// Update the particle
if (particle.accelerations != null) {
// Radial acceleration
Vector2 radial;
if (particle.pos[0] != 0 || particle.pos[1] != 0) {
radial = new Vector2.copy(particle.pos).normalize();
} else {
radial = new Vector2.zero();
if (particle.pos[0] != 0 || particle.pos[1] != 0) {
radial = new Vector2.copy(particle.pos).normalize();
} else {
radial = new Vector2.zero();
}
Vector2 tangential = new Vector2.copy(radial);
radial.scale(particle.accelerations.radialAccel);
// Tangential acceleration
double newY = tangential.x;
tangential.x = -tangential.y;
tangential.y = newY;
tangential.scale(particle.accelerations.tangentialAccel);
// (gravity + radial + tangential) * dt
Vector2 accel = (gravity + radial + tangential).scale(dt);
particle.dir += accel;
} else if (gravity[0] != 0.0 || gravity[1] != 0) {
// gravity
Vector2 accel = gravity.scale(dt);
particle.dir += accel;
}
Vector2 tangential = new Vector2.copy(radial);
radial.scale(particle.radialAccel);
// Tangential acceleration
double newY = tangential.x;
tangential.x = -tangential.y;
tangential.y = newY;
tangential.scale(particle.tangentialAccel);
// (gravity + radial + tangential) * dt
Vector2 accel = (gravity + radial + tangential).scale(dt);
particle.dir += accel;
particle.pos += new Vector2.copy(particle.dir).scale(dt);
// Update particle position
particle.pos[0] += particle.dir[0] * dt;
particle.pos[1] += particle.dir[1] * dt;
// Size
particle.size = math.max(particle.size + particle.deltaSize * dt, 0.0);
......@@ -182,7 +199,13 @@ class ParticleSystem extends Node {
particle.rotation += particle.deltaRotation * dt;
// Color
particle.colorPos = math.min(particle.colorPos + particle.deltaColorPos * dt, 1.0);
if (particle.simpleColorSequence != null) {
for (int i = 0; i < 4; i++) {
particle.simpleColorSequence[i] += particle.simpleColorSequence[i + 4] * dt;
}
} else {
particle.colorPos = math.min(particle.colorPos + particle.deltaColorPos * dt, 1.0);
}
}
if (autoRemoveOnFinish && _particles.length == 0 && _numEmittedParticles > 0) {
......@@ -218,18 +241,50 @@ class ParticleSystem extends Node {
double speedFinal = speed + speedVar * randomSignedDouble();
particle.dir = dirVector.scale(speedFinal);
// Radial acceleration
particle.radialAccel = radialAcceleration + radialAccelerationVar * randomSignedDouble();
// Accelerations
if (radialAcceleration != 0.0 || radialAccelerationVar != 0.0 ||
tangentialAcceleration != 0.0 || tangentialAccelerationVar != 0.0) {
particle.accelerations = new _ParticleAccelerations();
// Tangential acceleration
particle.tangentialAccel = tangentialAcceleration + tangentialAccelerationVar * randomSignedDouble();
// Radial acceleration
particle.accelerations.radialAccel = radialAcceleration + radialAccelerationVar * randomSignedDouble();
// Tangential acceleration
particle.accelerations.tangentialAccel = tangentialAcceleration + tangentialAccelerationVar * randomSignedDouble();
}
// Color
particle.colorPos = 0.0;
particle.deltaColorPos = 1.0 / particle.timeToLive;
if (alphaVar != 0 || redVar != 0 || greenVar != 0 || blueVar != 0) {
particle.colorSequence = new ColorSequence.copyWithVariance(colorSequence, alphaVar, redVar, greenVar, blueVar);
particle.colorSequence = _ColorSequenceUtil.copyWithVariance(colorSequence, alphaVar, redVar, greenVar, blueVar);
}
// Optimizes the case where there are only two colors in the sequence
if (colorSequence.colors.length == 2) {
Color startColor;
Color endColor;
if (particle.colorSequence != null) {
startColor = particle.colorSequence.colors[0];
endColor = particle.colorSequence.colors[1];
} else {
startColor = colorSequence.colors[0];
endColor = colorSequence.colors[1];
}
// First 4 elements are start ARGB, last 4 are delta ARGB
particle.simpleColorSequence = new Float64List(8);
particle.simpleColorSequence[0] = startColor.alpha.toDouble();
particle.simpleColorSequence[1] = startColor.red.toDouble();
particle.simpleColorSequence[2] = startColor.green.toDouble();
particle.simpleColorSequence[3] = startColor.blue.toDouble();
particle.simpleColorSequence[4] = (endColor.alpha.toDouble() - startColor.alpha.toDouble()) / particle.timeToLive;
particle.simpleColorSequence[5] = (endColor.red.toDouble() - startColor.red.toDouble()) / particle.timeToLive;
particle.simpleColorSequence[6] = (endColor.green.toDouble() - startColor.green.toDouble()) / particle.timeToLive;
particle.simpleColorSequence[7] = (endColor.blue.toDouble() - startColor.blue.toDouble()) / particle.timeToLive;
}
_particles.add(particle);
......@@ -242,6 +297,8 @@ class ParticleSystem extends Node {
List<Rect> rects = [];
List<Color> colors = [];
_paint.setTransferMode(transferMode);
for (_Particle particle in _particles) {
// Transform
double scos;
......@@ -250,9 +307,12 @@ class ParticleSystem extends Node {
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 {
} else if (particle.rotation != 0.0) {
scos = math.cos(convertDegrees2Radians(particle.rotation)) * particle.size;
ssin = math.sin(convertDegrees2Radians(particle.rotation)) * particle.size;
} else {
scos = particle.size;
ssin = 0.0;
}
RSTransform transform = new RSTransform(scos, ssin, particle.pos[0], particle.pos[1]);
transforms.add(transform);
......@@ -262,19 +322,55 @@ class ParticleSystem extends Node {
rects.add(rect);
// Color
Color particleColor;
if (particle.colorSequence != null) {
particleColor = particle.colorSequence.colorAtPosition(particle.colorPos);
if (particle.simpleColorSequence != null) {
Color particleColor = new Color.fromARGB(
particle.simpleColorSequence[0].toInt().clamp(0, 255),
particle.simpleColorSequence[1].toInt().clamp(0, 255),
particle.simpleColorSequence[2].toInt().clamp(0, 255),
particle.simpleColorSequence[3].toInt().clamp(0, 255));
colors.add(particleColor);
} else {
particleColor = colorSequence.colorAtPosition(particle.colorPos);
Color particleColor;
if (particle.colorSequence != null) {
particleColor = particle.colorSequence.colorAtPosition(particle.colorPos);
} else {
particleColor = colorSequence.colorAtPosition(particle.colorPos);
}
colors.add(particleColor);
}
colors.add(particleColor);
}
Paint paint = new Paint()..setTransferMode(transferMode)
..setFilterQuality(FilterQuality.low) // All Skia examples do this.
..isAntiAlias = false; // Antialiasing breaks SkCanvas.drawAtlas?
canvas.drawAtlas(texture.image, transforms, rects, colors,
TransferMode.modulate, null, paint);
TransferMode.modulate, null, _paint);
}
}
class _ColorSequenceUtil {
static ColorSequence copyWithVariance(
ColorSequence sequence,
int alphaVar,
int redVar,
int greenVar,
int blueVar
) {
ColorSequence copy = new ColorSequence.copy(sequence);
int i = 0;
for (Color color in sequence.colors) {
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);
int gNew = (color.green + gDelta).clamp(0, 255);
int bNew = (color.blue + bDelta).clamp(0, 255);
copy.colors[i] = new Color.fromARGB(aNew, rNew, gNew, bNew);
i++;
}
return copy;
}
}
......@@ -31,6 +31,10 @@ class SpriteBox extends RenderBox {
void set rootNode (NodeWithSize value) {
if (value == _rootNode) return;
// Ensure that the root node has a size
assert(value.size.width > 0);
assert(value.size.height > 0);
// Remove sprite box references
if (_rootNode != null) _removeSpriteBoxReference(_rootNode);
......@@ -334,9 +338,9 @@ class SpriteBox extends RenderBox {
_frameRate = 1.0/delta;
// Print frame rate
if (_numFrames % 60 == 0)
print("delta: $delta fps: $_frameRate");
// // Print frame rate
// if (_numFrames % 60 == 0)
// print("delta: $delta fps: $_frameRate");
_runActions(_rootNode, delta);
_callUpdate(_rootNode, delta);
......
......@@ -57,26 +57,26 @@ class GameMath {
if (x >= 0) {
if (y >= 0) {
if (x >= y)
return _atan2.ppy[(_Atan2Constants.size * y / x + 0.5).floor()];
return _atan2.ppy[(_Atan2Constants.size * y / x + 0.5).toInt()];
else
return _atan2.ppx[(_Atan2Constants.size * x / y + 0.5).floor()];
return _atan2.ppx[(_Atan2Constants.size * x / y + 0.5).toInt()];
} else {
if (x >= -y)
return _atan2.pny[(_Atan2Constants.ezis * y / x + 0.5).floor()];
return _atan2.pny[(_Atan2Constants.ezis * y / x + 0.5).toInt()];
else
return _atan2.pnx[(_Atan2Constants.ezis * x / y + 0.5).floor()];
return _atan2.pnx[(_Atan2Constants.ezis * x / y + 0.5).toInt()];
}
} else {
if (y >= 0) {
if (-x >= y)
return _atan2.npy[(_Atan2Constants.ezis * y / x + 0.5).floor()];
return _atan2.npy[(_Atan2Constants.ezis * y / x + 0.5).toInt()];
else
return _atan2.npx[(_Atan2Constants.ezis * x / y + 0.5).floor()];
return _atan2.npx[(_Atan2Constants.ezis * x / y + 0.5).toInt()];
} else {
if (x <= y)
return _atan2.nny[(_Atan2Constants.size * y / x + 0.5).floor()];
return _atan2.nny[(_Atan2Constants.size * y / x + 0.5).toInt()];
else
return _atan2.nnx[(_Atan2Constants.size * x / y + 0.5).floor()];
return _atan2.nnx[(_Atan2Constants.size * x / y + 0.5).toInt()];
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册