1 /** 2 * Copyright (c) 2006-2016 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 #ifndef LOVE_GRAPHICS_PARTICLE_SYSTEM_H 22 #define LOVE_GRAPHICS_PARTICLE_SYSTEM_H 23 24 // LOVE 25 #include "common/int.h" 26 #include "common/math.h" 27 #include "common/Vector.h" 28 #include "Drawable.h" 29 #include "Color.h" 30 #include "Quad.h" 31 #include "Texture.h" 32 33 // STL 34 #include <vector> 35 36 namespace love 37 { 38 namespace graphics 39 { 40 41 /** 42 * A class for creating, moving and drawing particles. 43 * A big thanks to bobthebloke.org 44 **/ 45 class ParticleSystem : public Drawable 46 { 47 public: 48 /** 49 * Type of distribution new particles are drawn from: None, uniform, normal, ellipse. 50 */ 51 enum AreaSpreadDistribution 52 { 53 DISTRIBUTION_NONE, 54 DISTRIBUTION_UNIFORM, 55 DISTRIBUTION_NORMAL, 56 DISTRIBUTION_ELLIPSE, 57 DISTRIBUTION_MAX_ENUM 58 }; 59 60 /** 61 * Insertion modes of new particles in the list: top, bottom, random. 62 */ 63 enum InsertMode 64 { 65 INSERT_MODE_TOP, 66 INSERT_MODE_BOTTOM, 67 INSERT_MODE_RANDOM, 68 INSERT_MODE_MAX_ENUM 69 }; 70 71 /** 72 * Maximum numbers of particles in a ParticleSystem. 73 * This limit comes from the fact that a quad requires four vertices and the 74 * OpenGL API where GLsizei is a signed int. 75 **/ 76 static const uint32 MAX_PARTICLES = LOVE_INT32_MAX / 4; 77 78 /** 79 * Creates a particle system with the specified buffer size and texture. 80 **/ 81 ParticleSystem(Texture *texture, uint32 buffer); 82 ParticleSystem(const ParticleSystem &p); 83 84 /** 85 * Deletes any allocated memory. 86 **/ 87 virtual ~ParticleSystem(); 88 89 /** 90 * Creates an identical copy of this ParticleSystem. The clone does not 91 * duplicate any existing particles from this ParticleSystem, just the 92 * settable parameters. 93 **/ 94 virtual ParticleSystem *clone() = 0; 95 96 /** 97 * Sets the texture used in the particle system. 98 * @param texture The new texture. 99 **/ 100 void setTexture(Texture *texture); 101 102 /** 103 * Returns the texture used when drawing the particle system. 104 **/ 105 Texture *getTexture() const; 106 107 /** 108 * Clears the current buffer and allocates the appropriate amount of space for the buffer. 109 * @param size The new buffer size. 110 **/ 111 virtual void setBufferSize(uint32 size); 112 113 /** 114 * Returns the total amount of particles this ParticleSystem can have active 115 * at any given point in time. 116 **/ 117 uint32 getBufferSize() const; 118 119 /** 120 * Sets the insert mode for new particles. 121 * @param mode The new insert mode. 122 */ 123 void setInsertMode(InsertMode mode); 124 125 /** 126 * Returns the current insert mode. 127 */ 128 InsertMode getInsertMode() const; 129 130 /** 131 * Sets the emission rate. 132 * @param rate The amount of particles per second. 133 **/ 134 void setEmissionRate(float rate); 135 136 /** 137 * Returns the number of particles created per second. 138 **/ 139 float getEmissionRate() const; 140 141 /** 142 * Sets the lifetime of the particle emitter (-1 means eternal) 143 * @param life The lifetime (in seconds). 144 **/ 145 void setEmitterLifetime(float life); 146 147 /** 148 * Returns the lifetime of the particle emitter. 149 **/ 150 float getEmitterLifetime() const; 151 152 /** 153 * Sets the life range of the particles. 154 * @param min The minimum life. 155 * @param max The maximum life (if 0, then becomes the same as minimum life). 156 **/ 157 void setParticleLifetime(float min, float max = 0); 158 159 /** 160 * Gets the lifetime of a particle. 161 * @param[out] min The minimum life. 162 * @param[out] max The maximum life. 163 **/ 164 void getParticleLifetime(float &min, float &max) const; 165 166 /** 167 * Sets the position of the center of the emitter. 168 * Used to move the emitter without changing the position of already existing particles. 169 * @param x The x-coordinate. 170 * @param y The y-coordinate. 171 **/ 172 void setPosition(float x, float y); 173 174 /** 175 * Returns the position of the emitter. 176 **/ 177 const love::Vector &getPosition() const; 178 179 /** 180 * Moves the position of the center of the emitter. 181 * When update is called, newly spawned particles will appear in a line 182 * between the old emitter position and where the emitter was moved to, 183 * resulting in a smoother-feeling particle system if moveTo is called 184 * repeatedly. 185 **/ 186 void moveTo(float x, float y); 187 188 /** 189 * Sets the emission area spread parameters and distribution type. The interpretation of 190 * the parameters depends on the distribution type: 191 * 192 * * None: Parameters are ignored. No area spread. 193 * * Uniform: Parameters denote maximal (symmetric) displacement from emitter position. 194 * * Normal: Parameters denote the standard deviation in x and y direction. x and y are assumed to be uncorrelated. 195 * @param x First parameter. Interpretation depends on distribution type. 196 * @param y Second parameter. Interpretation depends on distribution type. 197 * @param distribution Distribution type 198 **/ 199 void setAreaSpread(AreaSpreadDistribution distribution, float x, float y); 200 201 /** 202 * Returns area spread distribution type. 203 **/ 204 AreaSpreadDistribution getAreaSpreadDistribution() const; 205 206 /** 207 * Returns area spread parameters. 208 **/ 209 const love::Vector &getAreaSpreadParameters() const; 210 211 /** 212 * Sets the direction of the particle emitter. 213 * @param direction The direction (in degrees). 214 **/ 215 void setDirection(float direction); 216 217 /** 218 * Returns the direction of the particle emitter (in radians). 219 **/ 220 float getDirection() const; 221 222 /** 223 * Sets the spread of the particle emitter. 224 * @param spread The spread (in radians). 225 **/ 226 void setSpread(float spread); 227 228 /** 229 * Returns the directional spread of the emitter (in radians). 230 **/ 231 float getSpread() const; 232 233 /** 234 * Sets the speed of the particles. 235 * @param speed The speed. 236 **/ 237 void setSpeed(float speed); 238 239 /** 240 * Sets the speed of the particles. 241 * @param min The minimum speed. 242 * @param max The maximum speed. 243 **/ 244 void setSpeed(float min, float max); 245 246 /** 247 * Gets the speed of the particles. 248 * @param[out] min The minimum speed. 249 * @param[out] max The maximum speed. 250 **/ 251 void getSpeed(float &min, float &max) const; 252 253 /** 254 * Sets the linear acceleration (the acceleration along the x and y axes). 255 * @param x The acceleration along the x-axis. 256 * @param y The acceleration along the y-axis. 257 **/ 258 void setLinearAcceleration(float x, float y); 259 260 /** 261 * Sets the linear acceleration (the acceleration along the x and y axes). 262 * @param xmin The minimum amount of acceleration along the x-axis. 263 * @param ymin The minimum amount of acceleration along the y-axis. 264 * @param xmax The maximum amount of acceleration along the x-axis. 265 * @param ymax The maximum amount of acceleration along the y-axis. 266 **/ 267 void setLinearAcceleration(float xmin, float ymin, float xmax, float ymax); 268 269 /** 270 * Gets the linear acceleration of the particles. 271 * @param[out] min The minimum acceleration. 272 * @param[out] max The maximum acceleration. 273 **/ 274 void getLinearAcceleration(love::Vector &min, love::Vector &max) const; 275 276 /** 277 * Sets the radial acceleration (the acceleration towards the particle emitter). 278 * @param acceleration The amount of acceleration. 279 **/ 280 void setRadialAcceleration(float acceleration); 281 282 /** 283 * Sets the radial acceleration (the acceleration towards the particle emitter). 284 * @param min The minimum acceleration. 285 * @param max The maximum acceleration. 286 **/ 287 void setRadialAcceleration(float min, float max); 288 289 /** 290 * Gets the radial acceleration. 291 * @param[out] min The minimum amount of radial acceleration. 292 * @param[out] max The maximum amount of radial acceleration. 293 **/ 294 void getRadialAcceleration(float &min, float &max) const; 295 296 /** 297 * Sets the tangential acceleration (the acceleration perpendicular to the particle's direction). 298 * @param acceleration The amount of acceleration. 299 **/ 300 void setTangentialAcceleration(float acceleration); 301 302 /** 303 * Sets the tangential acceleration (the acceleration perpendicular to the particle's direction). 304 * @param min The minimum acceleration. 305 * @param max The maximum acceleration. 306 **/ 307 void setTangentialAcceleration(float min, float max); 308 309 /** 310 * Gets the tangential acceleration. 311 * @param[out] min The minimum tangential acceleration. 312 * @param[out] max The maximum tangential acceleration. 313 **/ 314 void getTangentialAcceleration(float &min, float &max) const; 315 316 /** 317 * Sets the amount of linear damping. Damping reduces the velocity of 318 * particles over time. A value of 0 corresponds to no damping. 319 **/ 320 void setLinearDamping(float min, float max); 321 322 /** 323 * Gets the current amount of linear damping. 324 **/ 325 void getLinearDamping(float &min, float &max) const; 326 327 /** 328 * Sets the size of the sprite (1.0 being the default size). 329 * @param size The size of the sprite. 330 **/ 331 void setSize(float size); 332 333 /** 334 * Sets the sizes of the sprite upon creation and upon death (1.0 being the default size). 335 * @param newSizes Array of sizes 336 **/ 337 void setSizes(const std::vector<float> &newSizes); 338 339 /** 340 * Returns the sizes of the particle sprites. 341 **/ 342 const std::vector<float> &getSizes() const; 343 344 /** 345 * Sets the amount of variation to the sprite's beginning size (0 being no variation and 1.0 a random size between start and end). 346 * @param variation The amount of variation. 347 **/ 348 void setSizeVariation(float variation); 349 350 /** 351 * Returns the amount of initial size variation between particles. 352 **/ 353 float getSizeVariation() const; 354 355 /** 356 * Sets the amount of rotation a sprite starts out with. 357 * @param rotation The amount of rotation. 358 **/ 359 void setRotation(float rotation); 360 361 /** 362 * Sets the amount of rotation a sprite starts out with (a random value between min and max). 363 * @param min The minimum amount of rotation. 364 * @param max The maximum amount of rotation. 365 **/ 366 void setRotation(float min, float max); 367 368 /** 369 * Gets the initial amount of rotation of a particle, in radians. 370 * @param[out] min The minimum initial rotation. 371 * @param[out] max The maximum initial rotation. 372 **/ 373 void getRotation(float &min, float &max) const; 374 375 /** 376 * Sets the spin of the sprite. 377 * @param spin The spin of the sprite (in degrees). 378 **/ 379 void setSpin(float spin); 380 381 /** 382 * Sets the spin of the sprite upon particle creation and death. 383 * @param start The spin of the sprite upon creation (in radians / second). 384 * @param end The spin of the sprite upon death (in radians / second). 385 **/ 386 void setSpin(float start, float end); 387 388 /** 389 * Gets the amount of spin of a particle during its lifetime. 390 * @param[out] start The initial spin, in radians / s. 391 * @param[out] end The final spin, in radians / s. 392 **/ 393 void getSpin(float &start, float &end) const; 394 395 /** 396 * Sets the variation of the start spin (0 being no variation and 1 being a random spin between start and end). 397 * @param variation The variation. 398 **/ 399 void setSpinVariation(float variation); 400 401 /** 402 * Returns the amount of variation of the start spin of a particle. 403 **/ 404 float getSpinVariation() const; 405 406 /** 407 * Sets the particles' offsets for rotation. 408 * @param x The x offset. 409 * @param y The y offset. 410 **/ 411 void setOffset(float x, float y); 412 413 /** 414 * Returns of the particle offset. 415 **/ 416 love::Vector getOffset() const; 417 418 /** 419 * Sets the color of the particles. 420 * @param newColors Array of colors 421 **/ 422 void setColor(const std::vector<Colorf> &newColors); 423 424 /** 425 * Returns the color of the particles. 426 **/ 427 std::vector<Colorf> getColor() const; 428 429 /** 430 * Sets a list of Quads to use for particles over their lifetime. 431 **/ 432 void setQuads(const std::vector<Quad *> &newQuads); 433 void setQuads(); 434 435 /** 436 * Gets the Quads used when drawing the particles. 437 **/ 438 std::vector<Quad *> getQuads() const; 439 440 /** 441 * sets whether particle angles & rotations are relative to their velocities. 442 **/ 443 void setRelativeRotation(bool enable); 444 bool hasRelativeRotation() const; 445 446 /** 447 * Returns the amount of particles that are currently active in the system. 448 **/ 449 uint32 getCount() const; 450 451 /** 452 * Starts/resumes the particle emitter. 453 **/ 454 void start(); 455 456 /** 457 * Stops the particle emitter and resets. 458 **/ 459 void stop(); 460 461 /** 462 * Pauses the particle emitter. 463 **/ 464 void pause(); 465 466 /** 467 * Resets the particle emitter. 468 **/ 469 void reset(); 470 471 /** 472 * Instantly emits a number of particles. 473 * @param num The number of particles to emit. 474 **/ 475 void emit(uint32 num); 476 477 /** 478 * Returns whether the particle emitter is active. 479 **/ 480 bool isActive() const; 481 482 /** 483 * Returns whether the particle emitter is paused. 484 **/ 485 bool isPaused() const; 486 487 bool isStopped() const; 488 489 /** 490 * Returns whether the particle system is empty of particles or not. 491 **/ 492 bool isEmpty() const; 493 494 /** 495 * Returns whether the amount of particles has reached the buffer limit or not. 496 **/ 497 bool isFull() const; 498 499 /** 500 * Updates the particle system. 501 * @param dt Time since last update. 502 **/ 503 void update(float dt); 504 505 static bool getConstant(const char *in, AreaSpreadDistribution &out); 506 static bool getConstant(AreaSpreadDistribution in, const char *&out); 507 508 static bool getConstant(const char *in, InsertMode &out); 509 static bool getConstant(InsertMode in, const char *&out); 510 511 protected: 512 513 // Represents a single particle. 514 struct Particle 515 { 516 Particle *prev; 517 Particle *next; 518 519 float lifetime; 520 float life; 521 522 love::Vector position; 523 524 // Particles gravitate towards this point. 525 love::Vector origin; 526 527 love::Vector velocity; 528 love::Vector linearAcceleration; 529 float radialAcceleration; 530 float tangentialAcceleration; 531 532 float linearDamping; 533 534 float size; 535 float sizeOffset; 536 float sizeIntervalSize; 537 538 float rotation; // Amount of rotation applied to the final angle. 539 float angle; 540 float spinStart; 541 float spinEnd; 542 543 Colorf color; 544 545 int quadIndex; 546 }; 547 548 // Pointer to the beginning of the allocated memory. 549 Particle *pMem; 550 551 // Pointer to a free particle. 552 Particle *pFree; 553 554 // Pointer to the start of the linked list. 555 Particle *pHead; 556 557 // Pointer to the end of the linked list. 558 Particle *pTail; 559 560 // The texture to be drawn. 561 StrongRef<Texture> texture; 562 563 // Whether the particle emitter is active. 564 bool active; 565 566 // Insert mode of new particles. 567 InsertMode insertMode; 568 569 // The maximum number of particles. 570 uint32 maxParticles; 571 572 // The number of active particles. 573 uint32 activeParticles; 574 575 // The emission rate (particles/sec). 576 float emissionRate; 577 578 // Used to determine when a particle should be emitted. 579 float emitCounter; 580 581 // The relative position of the particle emitter. 582 love::Vector position; 583 love::Vector prevPosition; 584 585 // Emission area spread. 586 AreaSpreadDistribution areaSpreadDistribution; 587 love::Vector areaSpread; 588 589 // The lifetime of the particle emitter (-1 means infinite) and the life it has left. 590 float lifetime; 591 float life; 592 593 // The particle life. 594 float particleLifeMin; 595 float particleLifeMax; 596 597 // The direction (and spread) the particles will be emitted in. Measured in radians. 598 float direction; 599 float spread; 600 601 // The speed. 602 float speedMin; 603 float speedMax; 604 605 // Acceleration along the x and y axes. 606 love::Vector linearAccelerationMin; 607 love::Vector linearAccelerationMax; 608 609 // Acceleration towards the emitter's center 610 float radialAccelerationMin; 611 float radialAccelerationMax; 612 613 // Acceleration perpendicular to the particle's direction. 614 float tangentialAccelerationMin; 615 float tangentialAccelerationMax; 616 617 float linearDampingMin; 618 float linearDampingMax; 619 620 // Size. 621 std::vector<float> sizes; 622 float sizeVariation; 623 624 // Rotation 625 float rotationMin; 626 float rotationMax; 627 628 // Spin. 629 float spinStart; 630 float spinEnd; 631 float spinVariation; 632 633 // Offsets 634 love::Vector offset; 635 636 // Is the ParticleSystem using a default offset? 637 bool defaultOffset; 638 639 // Color. 640 std::vector<Colorf> colors; 641 642 // Quads. 643 std::vector<StrongRef<Quad>> quads; 644 645 bool relativeRotation; 646 647 private: 648 649 void resetOffset(); 650 651 void createBuffers(size_t size); 652 void deleteBuffers(); 653 654 void addParticle(float t); 655 Particle *removeParticle(Particle *p); 656 657 // Called by addParticle. 658 void initParticle(Particle *p, float t); 659 void insertTop(Particle *p); 660 void insertBottom(Particle *p); 661 void insertRandom(Particle *p); 662 663 static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[]; 664 static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM> distributions; 665 666 static StringMap<InsertMode, INSERT_MODE_MAX_ENUM>::Entry insertModesEntries[]; 667 static StringMap<InsertMode, INSERT_MODE_MAX_ENUM> insertModes; 668 }; 669 670 } // graphics 671 } // love 672 673 #endif // LOVE_GRAPHICS_PARTICLE_SYSTEM_H 674