| OLD | NEW |
| (Empty) | |
| 1 part of sprites; |
| 2 |
| 3 class _Particle { |
| 4 Vector2 pos; |
| 5 Vector2 startPos; |
| 6 |
| 7 double colorPos; |
| 8 double deltaColorPos; |
| 9 |
| 10 double size; |
| 11 double deltaSize; |
| 12 |
| 13 double rotation; |
| 14 double deltaRotation; |
| 15 |
| 16 double timeToLive; |
| 17 |
| 18 Vector2 dir; |
| 19 double radialAccel; |
| 20 double tangentialAccel; |
| 21 |
| 22 ColorSequence colorSequence; |
| 23 } |
| 24 |
| 25 |
| 26 class ParticleSystem extends Node { |
| 27 |
| 28 Texture texture; |
| 29 |
| 30 double life; |
| 31 double lifeVar; |
| 32 |
| 33 Point posVar; |
| 34 |
| 35 double startSize; |
| 36 double startSizeVar; |
| 37 |
| 38 double endSize; |
| 39 double endSizeVar; |
| 40 |
| 41 double startRotation; |
| 42 double startRotationVar; |
| 43 |
| 44 double endRotation; |
| 45 double endRotationVar; |
| 46 |
| 47 bool rotateToMovement; |
| 48 |
| 49 double direction; |
| 50 double directionVar; |
| 51 |
| 52 double speed; |
| 53 double speedVar; |
| 54 |
| 55 double radialAcceleration; |
| 56 double radialAccelerationVar; |
| 57 |
| 58 double tangentialAcceleration; |
| 59 double tangentialAccelerationVar; |
| 60 |
| 61 Vector2 gravity; |
| 62 |
| 63 int maxParticles; |
| 64 int numParticlesToEmit; |
| 65 double emissionRate; |
| 66 bool autoRemoveOnFinish; |
| 67 |
| 68 ColorSequence colorSequence; |
| 69 int alphaVar; |
| 70 int redVar; |
| 71 int greenVar; |
| 72 int blueVar; |
| 73 TransferMode colorTransferMode; |
| 74 TransferMode transferMode; |
| 75 |
| 76 List<_Particle> _particles; |
| 77 |
| 78 double _emitCounter; |
| 79 double _elapsedTime; |
| 80 int _numEmittedParticles = 0; |
| 81 |
| 82 Math.Random _rand; |
| 83 |
| 84 ParticleSystem(this.texture, |
| 85 {this.life: 1.5, |
| 86 this.lifeVar: 1.0, |
| 87 this.posVar: Point.origin, |
| 88 this.startSize: 2.5, |
| 89 this.startSizeVar: 0.5, |
| 90 this.endSize: 0.0, |
| 91 this.endSizeVar: 0.0, |
| 92 this.startRotation: 0.0, |
| 93 this.startRotationVar: 0.0, |
| 94 this.endRotation: 0.0, |
| 95 this.endRotationVar: 0.0, |
| 96 this.rotateToMovement : false, |
| 97 this.direction: 0.0, |
| 98 this.directionVar: 360.0, |
| 99 this.speed: 100.0, |
| 100 this.speedVar: 50.0, |
| 101 this.radialAcceleration: 0.0, |
| 102 this.radialAccelerationVar: 0.0, |
| 103 this.tangentialAcceleration: 0.0, |
| 104 this.tangentialAccelerationVar: 0.0, |
| 105 this.gravity, |
| 106 this.maxParticles: 100, |
| 107 this.emissionRate: 50.0, |
| 108 this.colorSequence, |
| 109 this.alphaVar: 0, |
| 110 this.redVar: 0, |
| 111 this.greenVar: 0, |
| 112 this.blueVar: 0, |
| 113 this.colorTransferMode: TransferMode.multiply, |
| 114 this.transferMode: TransferMode.plus, |
| 115 this.numParticlesToEmit: 0, |
| 116 this.autoRemoveOnFinish: true}) { |
| 117 _particles = new List<_Particle>(); |
| 118 _rand = new Math.Random(); |
| 119 _emitCounter = 0.0; |
| 120 _elapsedTime = 0.0; |
| 121 if (gravity == null) gravity = new Vector2.zero(); |
| 122 if (colorSequence == null) colorSequence = new ColorSequence.fromStartAndEnd
Color(new Color(0xffffffff), new Color(0x00ffffff)); |
| 123 } |
| 124 |
| 125 void update(double dt) { |
| 126 |
| 127 // Create new particles |
| 128 double rate = 1.0 / emissionRate; |
| 129 |
| 130 if (_particles.length < maxParticles) { |
| 131 _emitCounter += dt; |
| 132 } |
| 133 |
| 134 while(_particles.length < maxParticles |
| 135 && _emitCounter > rate |
| 136 && (numParticlesToEmit == 0 || _numEmittedParticles < numParticlesToEmit)
) { |
| 137 // Add a new particle |
| 138 _addParticle(); |
| 139 _emitCounter -= rate; |
| 140 } |
| 141 |
| 142 _elapsedTime += dt; |
| 143 |
| 144 // Iterate over all particles |
| 145 for (int i = _particles.length -1; i >= 0; i--) { |
| 146 _Particle particle = _particles[i]; |
| 147 |
| 148 // Manage life time |
| 149 particle.timeToLive -= dt; |
| 150 if (particle.timeToLive <= 0) { |
| 151 _particles.removeAt(i); |
| 152 continue; |
| 153 } |
| 154 |
| 155 // Update the particle |
| 156 |
| 157 // Radial acceleration |
| 158 Vector2 radial; |
| 159 if (particle.pos[0] != 0 || particle.pos[1] != 0) { |
| 160 radial = new Vector2.copy(particle.pos).normalize(); |
| 161 } else { |
| 162 radial = new Vector2.zero(); |
| 163 } |
| 164 Vector2 tangential = new Vector2.copy(radial); |
| 165 radial.scale(particle.radialAccel); |
| 166 |
| 167 // Tangential acceleration |
| 168 double newY = tangential.x; |
| 169 tangential.x = -tangential.y; |
| 170 tangential.y = newY; |
| 171 tangential.scale(particle.tangentialAccel); |
| 172 |
| 173 // (gravity + radial + tangential) * dt |
| 174 Vector2 accel = (gravity + radial + tangential).scale(dt); |
| 175 particle.dir += accel; |
| 176 particle.pos += new Vector2.copy(particle.dir).scale(dt); |
| 177 |
| 178 // Size |
| 179 particle.size = Math.max(particle.size + particle.deltaSize * dt, 0.0); |
| 180 |
| 181 // Angle |
| 182 particle.rotation += particle.deltaRotation * dt; |
| 183 |
| 184 // Color |
| 185 particle.colorPos = Math.min(particle.colorPos + particle.deltaColorPos *
dt, 1.0); |
| 186 } |
| 187 |
| 188 if (autoRemoveOnFinish && _particles.length == 0 && _numEmittedParticles > 0
) { |
| 189 if (parent != null) removeFromParent(); |
| 190 } |
| 191 } |
| 192 |
| 193 void _addParticle() { |
| 194 |
| 195 _Particle particle = new _Particle(); |
| 196 |
| 197 // Time to live |
| 198 particle.timeToLive = Math.max(life + lifeVar * randMinus1To1(), 0.0); |
| 199 |
| 200 // Position |
| 201 Point srcPos = Point.origin; |
| 202 particle.pos = new Vector2(srcPos.x + posVar.x * randMinus1To1(), |
| 203 srcPos.y + posVar.y * randMinus1To1()); |
| 204 |
| 205 // Size |
| 206 particle.size = Math.max(startSize + startSizeVar * randMinus1To1(), 0.0); |
| 207 double endSizeFinal = Math.max(endSize + endSizeVar * randMinus1To1(), 0.0); |
| 208 particle.deltaSize = (endSizeFinal - particle.size) / particle.timeToLive; |
| 209 |
| 210 // Rotation |
| 211 particle.rotation = startRotation + startRotationVar * randMinus1To1(); |
| 212 double endRotationFinal = endRotation + endRotationVar * randMinus1To1(); |
| 213 particle.deltaRotation = (endRotationFinal - particle.rotation) / particle.t
imeToLive; |
| 214 |
| 215 // Direction |
| 216 double dirRadians = convertDegrees2Radians(direction + directionVar * randMi
nus1To1()); |
| 217 Vector2 dirVector = new Vector2(Math.cos(dirRadians), Math.sin(dirRadians)); |
| 218 double speedFinal = speed + speedVar * randMinus1To1(); |
| 219 particle.dir = dirVector.scale(speedFinal); |
| 220 |
| 221 // Radial acceleration |
| 222 particle.radialAccel = radialAcceleration + radialAccelerationVar * randMinu
s1To1(); |
| 223 |
| 224 // Tangential acceleration |
| 225 particle.tangentialAccel = tangentialAcceleration + tangentialAccelerationVa
r * randMinus1To1(); |
| 226 |
| 227 // Color |
| 228 particle.colorPos = 0.0; |
| 229 particle.deltaColorPos = 1.0 / particle.timeToLive; |
| 230 |
| 231 if (alphaVar != 0 || redVar != 0 || greenVar != 0 || blueVar != 0) { |
| 232 particle.colorSequence = new ColorSequence.copyWithVariance(colorSequence,
alphaVar, redVar, greenVar, blueVar); |
| 233 } |
| 234 |
| 235 _particles.add(particle); |
| 236 _numEmittedParticles++; |
| 237 } |
| 238 |
| 239 void paint(PaintingCanvas canvas) { |
| 240 |
| 241 List<RSTransform> transforms = []; |
| 242 List<Rect> rects = []; |
| 243 List<Color> colors = []; |
| 244 |
| 245 for (_Particle particle in _particles) { |
| 246 // Transform |
| 247 double scos; |
| 248 double ssin; |
| 249 if (rotateToMovement) { |
| 250 double extraRotation = Math.atan2(particle.dir[1], particle.dir[0]); |
| 251 scos = Math.cos(convertDegrees2Radians(particle.rotation) + extraRotatio
n) * particle.size; |
| 252 ssin = Math.sin(convertDegrees2Radians(particle.rotation) + extraRotatio
n) * particle.size; |
| 253 } else { |
| 254 scos = Math.cos(convertDegrees2Radians(particle.rotation)) * particle.si
ze; |
| 255 ssin = Math.sin(convertDegrees2Radians(particle.rotation)) * particle.si
ze; |
| 256 } |
| 257 RSTransform transform = new RSTransform(scos, ssin, particle.pos[0], parti
cle.pos[1]); |
| 258 transforms.add(transform); |
| 259 |
| 260 // Rect |
| 261 Rect rect = texture.frame; |
| 262 rects.add(rect); |
| 263 |
| 264 // Color |
| 265 Color particleColor; |
| 266 if (particle.colorSequence != null) { |
| 267 particleColor = particle.colorSequence.colorAtPosition(particle.colorPos
); |
| 268 } else { |
| 269 particleColor = colorSequence.colorAtPosition(particle.colorPos); |
| 270 } |
| 271 colors.add(particleColor); |
| 272 } |
| 273 |
| 274 drawAtlas(canvas, texture.image, transforms, rects, colors, TransferMode.mod
ulate, |
| 275 new Paint()..setTransferMode(transferMode)); |
| 276 } |
| 277 |
| 278 double randMinus1To1() => _rand.nextDouble() * 2.0 - 1.0; |
| 279 } |
| 280 |
| 281 // TODO: Needs bindings to Skia method in SkCanvas (exclude canvas parameter) |
| 282 void drawAtlas(Canvas canvas, Image image, List<RSTransform> transforms, List<Re
ct> rects, List<Color> colors, |
| 283 TransferMode transferMode, Paint paint) { |
| 284 assert(transforms.length == rects.length && transforms.length == colors.length
); |
| 285 |
| 286 Paint paint = new Paint(); |
| 287 |
| 288 Texture mainTexture = new Texture(image); |
| 289 |
| 290 for (int i = 0; i < transforms.length; i++) { |
| 291 RSTransform transform = transforms[i]; |
| 292 Rect rect = rects[i]; |
| 293 Color color = colors[i]; |
| 294 |
| 295 canvas.save(); |
| 296 |
| 297 Matrix4 matrix = new Matrix4(transform.scos, transform.ssin, 0.0, 0.0, |
| 298 -transform.ssin, transform.scos, 0.0, 0.0, |
| 299 0.0, 0.0, 1.0, 0.0, |
| 300 transform.tx, transform.ty, 0.0, 1.0); |
| 301 canvas.concat(matrix.storage); |
| 302 |
| 303 paint.setColorFilter(new ColorFilter.mode(color, transferMode)); |
| 304 paint.color = color; |
| 305 |
| 306 Texture texture = mainTexture.textureFromRect(rect); |
| 307 texture.drawTexture(canvas, new Point(-texture.size.width/2.0, -texture.size
.height/2.0), paint); |
| 308 |
| 309 canvas.restore(); |
| 310 } |
| 311 } |
| 312 |
| 313 // TODO: Needs bindings to Skia SkRSXform |
| 314 class RSTransform { |
| 315 double scos; |
| 316 double ssin; |
| 317 double tx; |
| 318 double ty; |
| 319 |
| 320 RSTransform(this.scos, this.ssin, this.tx, this.ty); |
| 321 } |
| OLD | NEW |