Example_-_Additive_Blend_Smoke_trail.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. //
  2. // Modified example of raylib.com !!
  3. //
  4. // Will change later on..
  5. //
  6. // I was watching a video of the game 'Gaia beyond' a space rpg where there were tiny space ships
  7. // and rockets with trails. I wanted to head into the direction of coding a small version of this.
  8. // Here I looked into how to do the smoke trails.. I'm not using a external image for the smoke
  9. // but created one in the code here.
  10. //
  11. #include "raylib.h"
  12. #define MAX_PARTICLES 200
  13. // Particle structure with basic data
  14. typedef struct {
  15. Vector2 position;
  16. Color color;
  17. float alpha;
  18. float size;
  19. float rotation;
  20. bool active; // NOTE: Use it to activate/deactive particle
  21. } Particle;
  22. int main(void)
  23. {
  24. // Initialization
  25. //--------------------------------------------------------------------------------------
  26. const int screenWidth = 800;
  27. const int screenHeight = 450;
  28. InitWindow(screenWidth, screenHeight, "raylib [core] example - generate random values");
  29. // Particles pool, reuse them!
  30. Particle mouseTail[MAX_PARTICLES] = { 0 };
  31. // Initialize particles
  32. for (int i = 0; i < MAX_PARTICLES; i++)
  33. {
  34. mouseTail[i].position = (Vector2){ 0, 0 };
  35. mouseTail[i].color = GRAY;//(Color){ GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 };
  36. mouseTail[i].alpha = 1.0f;
  37. mouseTail[i].size = (float)GetRandomValue(1, 30)/20.0f;
  38. mouseTail[i].rotation = (float)GetRandomValue(0, 360);
  39. mouseTail[i].active = false;
  40. }
  41. float gravity = 3.0f;
  42. // Create a Image in memory
  43. RenderTexture2D smoke = LoadRenderTexture(32, 32);
  44. BeginTextureMode(smoke);
  45. ClearBackground(BLANK);
  46. // Draw a base image(dark edges and white inside) for the additive blend mode smoke trail.
  47. for(int i=0;i<16;i++){
  48. BeginTextureMode(smoke);
  49. int c=255/16*i;
  50. DrawCircle(16,16,16-i/2,(Color){c,c,c,255});
  51. EndTextureMode(); // This needs to be called after every different draw command used. Do not forget to use begintexture also..
  52. }
  53. EndTextureMode(); // This needs to be called after every different draw command used. Do not forget to use begintexture also..
  54. // Start at blend additive mode for the white smoke trial.
  55. int blending = BLEND_ADDITIVE;
  56. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  57. //--------------------------------------------------------------------------------------
  58. // Main game loop
  59. while (!WindowShouldClose()) // Detect window close button or ESC key
  60. {
  61. // Update
  62. //----------------------------------------------------------------------------------
  63. //----------------------------------------------------------------------------------
  64. // Draw
  65. //----------------------------------------------------------------------------------
  66. BeginDrawing();
  67. ClearBackground(RAYWHITE);
  68. // Update
  69. //----------------------------------------------------------------------------------
  70. // Activate one particle every frame and Update active particles
  71. // NOTE: Particles initial position should be mouse position when activated
  72. // NOTE: Particles fall down with gravity and rotation... and disappear after 2 seconds (alpha = 0)
  73. // NOTE: When a particle disappears, active = false and it can be reused.
  74. for (int i = 0; i < MAX_PARTICLES; i++)
  75. {
  76. if (!mouseTail[i].active)
  77. {
  78. mouseTail[i].active = true;
  79. mouseTail[i].alpha = 1.0f;
  80. mouseTail[i].position = GetMousePosition();
  81. i = MAX_PARTICLES;
  82. }
  83. }
  84. for (int i = 0; i < MAX_PARTICLES; i++)
  85. {
  86. if (mouseTail[i].active)
  87. {
  88. mouseTail[i].position.y += gravity/2;
  89. mouseTail[i].alpha -= 0.005f;
  90. if (mouseTail[i].alpha <= 0.0f) mouseTail[i].active = false;
  91. mouseTail[i].rotation += 2.0f;
  92. }
  93. }
  94. if (IsKeyPressed(KEY_SPACE))
  95. {
  96. if (blending == BLEND_ALPHA) blending = BLEND_ADDITIVE;
  97. else blending = BLEND_ALPHA;
  98. }
  99. //----------------------------------------------------------------------------------
  100. // Draw
  101. //----------------------------------------------------------------------------------
  102. BeginDrawing();
  103. ClearBackground(DARKGRAY);
  104. BeginBlendMode(blending);
  105. // Draw active particles
  106. for (int i = 0; i < MAX_PARTICLES; i++)
  107. {
  108. if (mouseTail[i].active) DrawTexturePro(smoke.texture, (Rectangle){ 0.0f, 0.0f, (float)smoke.texture.width, (float)smoke.texture.height },
  109. (Rectangle){ mouseTail[i].position.x, mouseTail[i].position.y, smoke.texture.width*mouseTail[i].size, smoke.texture.height*mouseTail[i].size },
  110. (Vector2){ (float)(smoke.texture.width*mouseTail[i].size/2.0f), (float)(smoke.texture.height*mouseTail[i].size/2.0f) }, mouseTail[i].rotation,
  111. Fade(mouseTail[i].color, mouseTail[i].alpha));
  112. }
  113. EndBlendMode();
  114. DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, BLACK);
  115. if (blending == BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, BLACK);
  116. else DrawText("ADDITIVE BLENDING", 280, screenHeight - 40, 20, RAYWHITE);
  117. EndDrawing();
  118. //----------------------------------------------------------------------------------
  119. }
  120. // De-Initialization
  121. //--------------------------------------------------------------------------------------
  122. UnloadRenderTexture(smoke); // Unload render texture
  123. //--------------------------------------------------------------------------------------
  124. CloseWindow(); // Close window and OpenGL context
  125. //--------------------------------------------------------------------------------------
  126. return 0;
  127. }