Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: sky/sdk/example/game/lib/particle_system.dart

Issue 1216573009: Adds particle systems to sprites (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698