Mercurial > love-experiments
annotate src/modules/graphics/opengl/ParticleSystem.cpp @ 1127:13e6ca38c28c
Fix issue #437: Area-based particle spawn.
New particles are spawned around the particle emitter position according to a
configurabe distribution.
New functionality:
particlesystem:setAreaSpread(distributon, x, y)
distribution, x, y = particlesystem:getAreaSpread()
Where `distribution' is one of "none", "uniform", "normal".
`x' and `y' take different meaning based on the distribution:
* none: no area spread - particles spawned at emitter position.
* uniform: particle spawned at px,py in the rectangle around emitter
position ex,ey, i.e.:
ex - x < px < ex + x, ey - y < py < ey + y,
* normal: particle position drawn from a normal/gaussian distribution
with mean ex,ey and standard deviation x,y, i.e.:
px \in N(ex, x²), py \in N(ey, y²).
| author | vrld <vrld@vrld.org> |
|---|---|
| date | Mon, 10 Sep 2012 19:58:44 +0200 |
| parents | 86a44f2bc38f |
| children | 7c7332becb70 77889bd62149 |
| rev | line source |
|---|---|
| 1096 | 1 /** |
| 2 * Copyright (c) 2006-2012 LOVE Development Team | |
| 3 * | |
| 4 * This software is provided 'as-is', without any express or implied | |
| 5 * warranty. In no event will the authors be held liable for any damages | |
| 6 * arising from the use of this software. | |
| 7 * | |
| 8 * Permission is granted to anyone to use this software for any purpose, | |
| 9 * including commercial applications, and to alter it and redistribute it | |
| 10 * freely, subject to the following restrictions: | |
| 11 * | |
| 12 * 1. The origin of this software must not be misrepresented; you must not | |
| 13 * claim that you wrote the original software. If you use this software | |
| 14 * in a product, an acknowledgment in the product documentation would be | |
| 15 * appreciated but is not required. | |
| 16 * 2. Altered source versions must be plainly marked as such, and must not be | |
| 17 * misrepresented as being the original software. | |
| 18 * 3. This notice may not be removed or altered from any source distribution. | |
| 19 **/ | |
| 20 | |
| 21 #include "ParticleSystem.h" | |
| 22 | |
| 23 #include "common/math.h" | |
| 24 | |
| 25 #include "GLee.h" | |
| 26 #include <cmath> | |
| 27 #include <cstdlib> | |
| 28 | |
| 29 namespace love | |
| 30 { | |
| 31 namespace graphics | |
| 32 { | |
| 33 namespace opengl | |
| 34 { | |
| 35 | |
| 36 namespace | |
| 37 { | |
| 38 Colorf colorToFloat(const Color &c) | |
| 39 { | |
| 40 return Colorf((GLfloat)c.r/255.0f, (GLfloat)c.g/255.0f, (GLfloat)c.b/255.0f, (GLfloat)c.a/255.0f); | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 float calculate_variation(float inner, float outer, float var) | |
| 45 { | |
| 46 float low = inner - (outer/2.0f)*var; | |
| 47 float high = inner + (outer/2.0f)*var; | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
48 float r = random(); |
| 1096 | 49 return low*(1-r)+high*r; |
| 50 } | |
| 51 | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
52 StringMap<ParticleSystem::AreaSpreadDistribution, ParticleSystem::DISTRIBUTION_MAX_ENUM>::Entry ParticleSystem::distributionsEntries[] = { |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
53 { "none", ParticleSystem::DISTRIBUTION_NONE }, |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
54 { "uniform", ParticleSystem::DISTRIBUTION_UNIFORM }, |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
55 { "normal", ParticleSystem::DISTRIBUTION_NORMAL }, |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
56 }; |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
57 |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
58 StringMap<ParticleSystem::AreaSpreadDistribution, ParticleSystem::DISTRIBUTION_MAX_ENUM> ParticleSystem::distributions(ParticleSystem::distributionsEntries, sizeof(ParticleSystem::distributionsEntries)); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
59 |
| 1096 | 60 |
| 61 ParticleSystem::ParticleSystem(Image *sprite, unsigned int buffer) | |
| 62 : pStart(0) | |
| 63 , pLast(0) | |
| 64 , pEnd(0) | |
| 65 , active(true) | |
| 66 , emissionRate(0) | |
| 67 , emitCounter(0) | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
68 , areaSpreadDistribution(DISTRIBUTION_NONE) |
| 1096 | 69 , lifetime(-1) |
| 70 , life(0) | |
| 71 , particleLifeMin(0) | |
| 72 , particleLifeMax(0) | |
| 73 , direction(0) | |
| 74 , spread(0) | |
| 75 , relative(false) | |
| 76 , speedMin(0) | |
| 77 , speedMax(0) | |
| 78 , gravityMin(0) | |
| 79 , gravityMax(0) | |
| 80 , radialAccelerationMin(0) | |
| 81 , radialAccelerationMax(0) | |
| 82 , tangentialAccelerationMin(0) | |
| 83 , tangentialAccelerationMax(0) | |
| 84 , sizeVariation(0) | |
| 85 , rotationMin(0) | |
| 86 , rotationMax(0) | |
| 87 , spinStart(0) | |
| 88 , spinEnd(0) | |
| 89 , spinVariation(0) | |
| 90 , offsetX(sprite->getWidth()*0.5f) | |
| 91 , offsetY(sprite->getHeight()*0.5f) | |
| 92 { | |
| 93 this->sprite = sprite; | |
| 94 sprite->retain(); | |
| 95 sizes.push_back(1.0f); | |
| 96 colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); | |
| 97 setBufferSize(buffer); | |
| 98 } | |
| 99 | |
| 100 ParticleSystem::~ParticleSystem() | |
| 101 { | |
| 102 if (this->sprite != 0) | |
| 103 this->sprite->release(); | |
| 104 | |
| 105 if (pStart != 0) | |
| 106 delete [] pStart; | |
| 107 } | |
| 108 | |
| 109 void ParticleSystem::add() | |
| 110 { | |
| 111 if (isFull()) return; | |
| 112 | |
| 113 float min,max; | |
| 114 | |
| 115 min = particleLifeMin; | |
| 116 max = particleLifeMax; | |
| 117 if (min == max) | |
| 118 pLast->life = min; | |
| 119 else | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
120 pLast->life = random(min, max); |
| 1096 | 121 pLast->lifetime = pLast->life; |
| 122 | |
| 123 pLast->position[0] = position.getX(); | |
| 124 pLast->position[1] = position.getY(); | |
| 125 | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
126 switch (areaSpreadDistribution) |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
127 { |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
128 case DISTRIBUTION_UNIFORM: |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
129 pLast->position[0] += random(-areaSpread.getX(), areaSpread.getX()); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
130 pLast->position[1] += random(-areaSpread.getY(), areaSpread.getY()); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
131 break; |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
132 case DISTRIBUTION_NORMAL: |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
133 pLast->position[0] += random_normal(areaSpread.getX()); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
134 pLast->position[1] += random_normal(areaSpread.getY()); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
135 break; |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
136 case DISTRIBUTION_NONE: |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
137 default: |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
138 break; |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
139 } |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
140 |
| 1096 | 141 min = direction - spread/2.0f; |
| 142 max = direction + spread/2.0f; | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
143 pLast->direction = random(min, max); |
| 1096 | 144 |
| 145 pLast->origin = position; | |
| 146 | |
| 147 min = speedMin; | |
| 148 max = speedMax; | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
149 float speed = random(min, max); |
| 1096 | 150 pLast->speed = love::Vector(cos(pLast->direction), sin(pLast->direction)); |
| 151 pLast->speed *= speed; | |
| 152 | |
| 153 min = gravityMin; | |
| 154 max = gravityMax; | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
155 pLast->gravity = random(min, max); |
| 1096 | 156 |
| 157 min = radialAccelerationMin; | |
| 158 max = radialAccelerationMax; | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
159 pLast->radialAcceleration = random(min, max); |
| 1096 | 160 |
| 161 min = tangentialAccelerationMin; | |
| 162 max = tangentialAccelerationMax; | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
163 pLast->tangentialAcceleration = random(min, max); |
| 1096 | 164 |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
165 pLast->sizeOffset = random(sizeVariation); // time offset for size change |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
166 pLast->sizeIntervalSize = (1.0f - random(sizeVariation)) - pLast->sizeOffset; |
| 1096 | 167 pLast->size = sizes[(size_t)(pLast->sizeOffset - .5f) * (sizes.size() - 1)]; |
| 168 | |
| 169 min = rotationMin; | |
| 170 max = rotationMax; | |
| 171 pLast->spinStart = calculate_variation(spinStart, spinEnd, spinVariation); | |
| 172 pLast->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation); | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
173 pLast->rotation = random(min, max); |
| 1096 | 174 |
| 175 pLast->color = colors[0]; | |
| 176 | |
| 177 pLast++; | |
| 178 } | |
| 179 | |
| 180 void ParticleSystem::remove(particle *p) | |
| 181 { | |
| 182 if (!isEmpty()) | |
| 183 { | |
| 184 *p = *(--pLast); | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 void ParticleSystem::setSprite(Image *image) | |
| 189 { | |
| 190 if (sprite != 0) | |
| 191 sprite->release(); | |
| 192 | |
| 193 sprite = image; | |
| 194 sprite->retain(); | |
| 195 } | |
| 196 | |
| 197 void ParticleSystem::setBufferSize(unsigned int size) | |
| 198 { | |
| 199 // delete previous data | |
| 200 delete [] pStart; | |
| 201 | |
| 202 pLast = pStart = new particle[size]; | |
| 203 | |
| 204 pEnd = pStart + size; | |
| 205 } | |
| 206 | |
| 207 void ParticleSystem::setEmissionRate(int rate) | |
| 208 { | |
| 209 emissionRate = rate; | |
| 210 } | |
| 211 | |
| 212 void ParticleSystem::setLifetime(float life) | |
| 213 { | |
| 214 this->life = lifetime = life; | |
| 215 } | |
| 216 | |
| 217 void ParticleSystem::setParticleLife(float min, float max) | |
| 218 { | |
| 219 particleLifeMin = min; | |
| 220 if (max == 0) | |
| 221 particleLifeMax = min; | |
| 222 else | |
| 223 particleLifeMax = max; | |
| 224 } | |
| 225 | |
| 226 void ParticleSystem::setPosition(float x, float y) | |
| 227 { | |
| 228 position = love::Vector(x, y); | |
| 229 } | |
| 230 | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
231 |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
232 void ParticleSystem::setAreaSpread(AreaSpreadDistribution distribution, float x, float y) |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
233 { |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
234 areaSpread = love::Vector(x, y); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
235 areaSpreadDistribution = distribution; |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
236 } |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
237 |
| 1096 | 238 void ParticleSystem::setDirection(float direction) |
| 239 { | |
| 240 this->direction = direction; | |
| 241 } | |
| 242 | |
| 243 void ParticleSystem::setSpread(float spread) | |
| 244 { | |
| 245 this->spread = spread; | |
| 246 } | |
| 247 | |
| 248 void ParticleSystem::setRelativeDirection(bool relative) | |
| 249 { | |
| 250 this->relative = relative; | |
| 251 } | |
| 252 | |
| 253 void ParticleSystem::setSpeed(float speed) | |
| 254 { | |
| 255 speedMin = speedMax = speed; | |
| 256 } | |
| 257 | |
| 258 void ParticleSystem::setSpeed(float min, float max) | |
| 259 { | |
| 260 speedMin = min; | |
| 261 speedMax = max; | |
| 262 } | |
| 263 | |
| 264 void ParticleSystem::setGravity(float gravity) | |
| 265 { | |
| 266 gravityMin = gravityMax = gravity; | |
| 267 } | |
| 268 | |
| 269 void ParticleSystem::setGravity(float min, float max) | |
| 270 { | |
| 271 gravityMin = min; | |
| 272 gravityMax = max; | |
| 273 } | |
| 274 | |
| 275 void ParticleSystem::setRadialAcceleration(float acceleration) | |
| 276 { | |
| 277 radialAccelerationMin = radialAccelerationMax = acceleration; | |
| 278 } | |
| 279 | |
| 280 void ParticleSystem::setRadialAcceleration(float min, float max) | |
| 281 { | |
| 282 radialAccelerationMin = min; | |
| 283 radialAccelerationMax = max; | |
| 284 } | |
| 285 | |
| 286 void ParticleSystem::setTangentialAcceleration(float acceleration) | |
| 287 { | |
| 288 tangentialAccelerationMin = tangentialAccelerationMax = acceleration; | |
| 289 } | |
| 290 | |
| 291 void ParticleSystem::setTangentialAcceleration(float min, float max) | |
| 292 { | |
| 293 tangentialAccelerationMin = min; | |
| 294 tangentialAccelerationMax = max; | |
| 295 } | |
| 296 | |
| 297 void ParticleSystem::setSize(float size) | |
| 298 { | |
| 299 sizes.resize(1); | |
| 300 sizes[0] = size; | |
| 301 } | |
| 302 | |
| 303 void ParticleSystem::setSize(const std::vector<float> &newSizes, float variation) | |
| 304 { | |
| 305 sizes = newSizes; | |
| 306 sizeVariation = variation; | |
| 307 } | |
| 308 | |
| 309 void ParticleSystem::setSizeVariation(float variation) | |
| 310 { | |
| 311 sizeVariation = variation; | |
| 312 } | |
| 313 | |
| 314 void ParticleSystem::setRotation(float rotation) | |
| 315 { | |
| 316 rotationMin = rotationMax = rotation; | |
| 317 } | |
| 318 | |
| 319 void ParticleSystem::setRotation(float min, float max) | |
| 320 { | |
| 321 rotationMin = min; | |
| 322 rotationMax = max; | |
| 323 } | |
| 324 | |
| 325 void ParticleSystem::setSpin(float spin) | |
| 326 { | |
| 327 spinStart = spin; | |
| 328 spinEnd = spin; | |
| 329 } | |
| 330 | |
| 331 void ParticleSystem::setSpin(float start, float end) | |
| 332 { | |
| 333 spinStart = start; | |
| 334 spinEnd = end; | |
| 335 } | |
| 336 | |
| 337 void ParticleSystem::setSpin(float start, float end, float variation) | |
| 338 { | |
| 339 spinStart = start; | |
| 340 spinEnd = end; | |
| 341 spinVariation = variation; | |
| 342 } | |
| 343 | |
| 344 void ParticleSystem::setSpinVariation(float variation) | |
| 345 { | |
| 346 spinVariation = variation; | |
| 347 } | |
| 348 | |
| 349 void ParticleSystem::setColor(const Color &color) | |
| 350 { | |
| 351 colors.resize(1); | |
| 352 colors[0] = colorToFloat(color); | |
| 353 } | |
| 354 | |
| 355 void ParticleSystem::setColor(const std::vector<Color> &newColors) | |
| 356 { | |
| 357 colors.resize(newColors.size()); | |
| 358 for (size_t i = 0; i < newColors.size(); ++i) | |
| 359 colors[i] = colorToFloat(newColors[i]); | |
| 360 } | |
| 361 | |
| 362 void ParticleSystem::setOffset(float x, float y) | |
| 363 { | |
| 364 offsetX = x; | |
| 365 offsetY = y; | |
| 366 } | |
| 367 | |
| 368 float ParticleSystem::getX() const | |
| 369 { | |
| 370 return position.getX(); | |
| 371 } | |
| 372 | |
| 373 float ParticleSystem::getY() const | |
| 374 { | |
| 375 return position.getY(); | |
| 376 } | |
| 377 | |
| 378 const love::Vector &ParticleSystem::getPosition() const | |
| 379 { | |
| 380 return position; | |
| 381 } | |
| 382 | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
383 ParticleSystem::AreaSpreadDistribution ParticleSystem::getAreaSpreadDistribution() const |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
384 { |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
385 return areaSpreadDistribution; |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
386 } |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
387 |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
388 const love::Vector &ParticleSystem::getAreaSpreadParameters() const |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
389 { |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
390 return areaSpread; |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
391 } |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
392 |
| 1096 | 393 float ParticleSystem::getDirection() const |
| 394 { | |
| 395 return direction; | |
| 396 } | |
| 397 | |
| 398 float ParticleSystem::getSpread() const | |
| 399 { | |
| 400 return spread; | |
| 401 } | |
| 402 | |
| 403 float ParticleSystem::getOffsetX() const | |
| 404 { | |
| 405 return offsetX; | |
| 406 } | |
| 407 | |
| 408 float ParticleSystem::getOffsetY() const | |
| 409 { | |
| 410 return offsetY; | |
| 411 } | |
| 412 | |
| 413 int ParticleSystem::count() const | |
| 414 { | |
| 415 return (int)(pLast - pStart); | |
| 416 } | |
| 417 | |
| 418 void ParticleSystem::start() | |
| 419 { | |
| 420 active = true; | |
| 421 } | |
| 422 | |
| 423 void ParticleSystem::stop() | |
| 424 { | |
| 425 active = false; | |
| 426 life = lifetime; | |
| 427 emitCounter = 0; | |
| 428 } | |
| 429 | |
| 430 void ParticleSystem::pause() | |
| 431 { | |
| 432 active = false; | |
| 433 } | |
| 434 | |
| 435 void ParticleSystem::reset() | |
| 436 { | |
| 437 pLast = pStart; | |
| 438 life = lifetime; | |
| 439 emitCounter = 0; | |
| 440 } | |
| 441 | |
| 442 bool ParticleSystem::isActive() const | |
| 443 { | |
| 444 return active; | |
| 445 } | |
| 446 | |
| 447 bool ParticleSystem::isEmpty() const | |
| 448 { | |
| 449 return pStart == pLast; | |
| 450 } | |
| 451 | |
| 452 bool ParticleSystem::isFull() const | |
| 453 { | |
| 454 return pLast == pEnd; | |
| 455 } | |
| 456 | |
| 457 void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const | |
| 458 { | |
| 459 if (sprite == 0) return; // just in case of failure | |
| 460 | |
| 461 glPushMatrix(); | |
| 462 glPushAttrib(GL_CURRENT_BIT); | |
| 463 | |
| 464 Matrix t; | |
| 465 t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky); | |
| 466 glMultMatrixf((const GLfloat *)t.getElements()); | |
| 467 | |
| 468 particle *p = pStart; | |
| 469 while (p != pLast) | |
| 470 { | |
| 471 glPushMatrix(); | |
| 472 | |
| 473 glColor4f(p->color.r, p->color.g, p->color.b, p->color.a); | |
| 474 sprite->draw(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f); | |
| 475 | |
| 476 glPopMatrix(); | |
| 477 p++; | |
| 478 } | |
| 479 | |
| 480 glPopAttrib(); | |
| 481 glPopMatrix(); | |
| 482 } | |
| 483 | |
| 484 void ParticleSystem::update(float dt) | |
| 485 { | |
| 486 // Traverse all particles and update. | |
| 487 particle *p = pStart; | |
| 488 | |
| 489 // Make some more particles. | |
| 490 if (active) | |
| 491 { | |
| 492 float rate = 1.0f / emissionRate; // the amount of time between each particle emit | |
| 493 emitCounter += dt; | |
| 494 while (emitCounter > rate) | |
| 495 { | |
| 496 add(); | |
| 497 emitCounter -= rate; | |
| 498 } | |
| 499 /*int particles = (int)(emissionRate * dt); | |
| 500 for (int i = 0; i != particles; i++) | |
| 501 add();*/ | |
| 502 | |
| 503 life -= dt; | |
| 504 if (lifetime != -1 && life < 0) | |
| 505 stop(); | |
| 506 } | |
| 507 | |
| 508 while (p != pLast) | |
| 509 { | |
| 510 // Decrease lifespan. | |
| 511 p->life -= dt; | |
| 512 | |
| 513 if (p->life > 0) | |
| 514 { | |
| 515 | |
| 516 // Temp variables. | |
| 517 love::Vector radial, tangential, gravity(0, p->gravity); | |
| 518 love::Vector ppos(p->position[0], p->position[1]); | |
| 519 | |
| 520 // Get vector from particle center to particle. | |
| 521 radial = ppos - p->origin; | |
| 522 radial.normalize(); | |
| 523 tangential = radial; | |
| 524 | |
| 525 // Resize radial acceleration. | |
| 526 radial *= p->radialAcceleration; | |
| 527 | |
| 528 // Calculate tangential acceleration. | |
| 529 { | |
| 530 float a = tangential.getX(); | |
| 531 tangential.setX(-tangential.getY()); | |
| 532 tangential.setY(a); | |
| 533 } | |
| 534 | |
| 535 // Resize tangential. | |
| 536 tangential *= p->tangentialAcceleration; | |
| 537 | |
| 538 // Update position. | |
| 539 p->speed += (radial+tangential+gravity)*dt; | |
| 540 | |
| 541 // Modify position. | |
| 542 ppos += p->speed * dt; | |
| 543 | |
| 544 p->position[0] = ppos.getX(); | |
| 545 p->position[1] = ppos.getY(); | |
| 546 | |
| 547 const float t = 1.0f - p->life / p->lifetime; | |
| 548 | |
| 549 // Rotate. | |
| 550 p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t)*dt; | |
| 551 | |
| 552 // Change size according to given intervals: | |
| 553 // i = 0 1 2 3 n-1 | |
| 554 // |-------|-------|------|--- ... ---| | |
| 555 // t = 0 1/(n-1) 3/(n-1) 1 | |
| 556 // | |
| 557 // `s' is the interpolation variable scaled to the current | |
| 558 // interval width, e.g. if n = 5 and t = 0.3, then the current | |
| 559 // indices are 1,2 and s = 0.3 - 0.25 = 0.05 | |
| 560 float s = p->sizeOffset + t * p->sizeIntervalSize; // size variation | |
| 561 s *= (float)(sizes.size() - 1); // 0 <= s < sizes.size() | |
| 562 size_t i = (size_t)s; | |
| 563 size_t k = (i == sizes.size() - 1) ? i : i + 1; // boundary check (prevents failing on t = 1.0f) | |
| 564 s -= (float)i; // transpose s to be in interval [0:1]: i <= s < i + 1 ~> 0 <= s < 1 | |
| 565 p->size = sizes[i] * (1.0f - s) + sizes[k] * s; | |
| 566 | |
| 567 // Update color according to given intervals (as above) | |
| 568 s = t * (float)(colors.size() - 1); | |
| 569 i = (size_t)s; | |
| 570 k = (i == colors.size() - 1) ? i : i + 1; | |
| 571 s -= (float)i; // 0 <= s <= 1 | |
| 572 p->color = colors[i] * (1.0f - s) + colors[k] * s; | |
| 573 | |
| 574 // Next particle. | |
| 575 p++; | |
| 576 } | |
| 577 else | |
| 578 { | |
| 579 remove(p); | |
| 580 | |
| 581 if (p >= pLast) | |
| 582 return; | |
| 583 } // else | |
| 584 } // while | |
| 585 } | |
| 586 | |
|
1127
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
587 bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out) |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
588 { |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
589 return distributions.find(in, out); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
590 } |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
591 |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
592 bool ParticleSystem::getConstant(AreaSpreadDistribution in, const char *&out) |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
593 { |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
594 return distributions.find(in, out); |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
595 } |
|
13e6ca38c28c
Fix issue #437: Area-based particle spawn.
vrld <vrld@vrld.org>
parents:
1096
diff
changeset
|
596 |
| 1096 | 597 } // opengl |
| 598 } // graphics | |
| 599 } // love |
