textures_particles_blending.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*******************************************************************************************
  2. *
  3. * raylib [textures] example - particles blending
  4. *
  5. * Example complexity rating: [★☆☆☆] 1/4
  6. *
  7. * Example originally created with raylib 1.7, last time updated with raylib 3.5
  8. *
  9. * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
  10. * BSD-like license that allows static linking with closed source software
  11. *
  12. * Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
  13. *
  14. ********************************************************************************************/
  15. #include "raylib.h"
  16. #define MAX_PARTICLES 200
  17. //----------------------------------------------------------------------------------
  18. // Types and Structures Definition
  19. //----------------------------------------------------------------------------------
  20. // Particle structure
  21. typedef struct {
  22. Vector2 position;
  23. Color color;
  24. float alpha;
  25. float size;
  26. float rotation;
  27. bool active; // NOTE: Use it to activate/deactive particle
  28. } Particle;
  29. //------------------------------------------------------------------------------------
  30. // Program main entry point
  31. //------------------------------------------------------------------------------------
  32. int main(void)
  33. {
  34. // Initialization
  35. //--------------------------------------------------------------------------------------
  36. const int screenWidth = 800;
  37. const int screenHeight = 450;
  38. InitWindow(screenWidth, screenHeight, "raylib [textures] example - particles blending");
  39. // Particles pool, reuse them!
  40. Particle mouseTail[MAX_PARTICLES] = { 0 };
  41. // Initialize particles
  42. for (int i = 0; i < MAX_PARTICLES; i++)
  43. {
  44. mouseTail[i].position = (Vector2){ 0, 0 };
  45. mouseTail[i].color = (Color){ GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 };
  46. mouseTail[i].alpha = 1.0f;
  47. mouseTail[i].size = (float)GetRandomValue(1, 30)/20.0f;
  48. mouseTail[i].rotation = (float)GetRandomValue(0, 360);
  49. mouseTail[i].active = false;
  50. }
  51. float gravity = 3.0f;
  52. Texture2D smoke = LoadTexture("resources/spark_flame.png");
  53. int blending = BLEND_ALPHA;
  54. SetTargetFPS(60);
  55. //--------------------------------------------------------------------------------------
  56. // Main game loop
  57. while (!WindowShouldClose()) // Detect window close button or ESC key
  58. {
  59. // Update
  60. //----------------------------------------------------------------------------------
  61. // Activate one particle every frame and Update active particles
  62. // NOTE: Particles initial position should be mouse position when activated
  63. // NOTE: Particles fall down with gravity and rotation... and disappear after 2 seconds (alpha = 0)
  64. // NOTE: When a particle disappears, active = false and it can be reused
  65. for (int i = 0; i < MAX_PARTICLES; i++)
  66. {
  67. if (!mouseTail[i].active)
  68. {
  69. mouseTail[i].active = true;
  70. mouseTail[i].alpha = 1.0f;
  71. mouseTail[i].position = GetMousePosition();
  72. i = MAX_PARTICLES;
  73. }
  74. }
  75. for (int i = 0; i < MAX_PARTICLES; i++)
  76. {
  77. if (mouseTail[i].active)
  78. {
  79. mouseTail[i].position.y += gravity/2;
  80. mouseTail[i].alpha -= 0.005f;
  81. if (mouseTail[i].alpha <= 0.0f) mouseTail[i].active = false;
  82. mouseTail[i].rotation += 2.0f;
  83. }
  84. }
  85. if (IsKeyPressed(KEY_SPACE))
  86. {
  87. if (blending == BLEND_ALPHA) blending = BLEND_ADDITIVE;
  88. else blending = BLEND_ALPHA;
  89. }
  90. //----------------------------------------------------------------------------------
  91. // Draw
  92. //----------------------------------------------------------------------------------
  93. BeginDrawing();
  94. ClearBackground(DARKGRAY);
  95. BeginBlendMode(blending);
  96. // Draw active particles
  97. for (int i = 0; i < MAX_PARTICLES; i++)
  98. {
  99. if (mouseTail[i].active) DrawTexturePro(smoke, (Rectangle){ 0.0f, 0.0f, (float)smoke.width, (float)smoke.height },
  100. (Rectangle){ mouseTail[i].position.x, mouseTail[i].position.y, smoke.width*mouseTail[i].size, smoke.height*mouseTail[i].size },
  101. (Vector2){ (float)(smoke.width*mouseTail[i].size/2.0f), (float)(smoke.height*mouseTail[i].size/2.0f) }, mouseTail[i].rotation,
  102. Fade(mouseTail[i].color, mouseTail[i].alpha));
  103. }
  104. EndBlendMode();
  105. DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, BLACK);
  106. if (blending == BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, BLACK);
  107. else DrawText("ADDITIVE BLENDING", 280, screenHeight - 40, 20, RAYWHITE);
  108. EndDrawing();
  109. //----------------------------------------------------------------------------------
  110. }
  111. // De-Initialization
  112. //--------------------------------------------------------------------------------------
  113. UnloadTexture(smoke);
  114. CloseWindow(); // Close window and OpenGL context
  115. //--------------------------------------------------------------------------------------
  116. return 0;
  117. }