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