@@ -191,6 +191,110 @@ void render_starfield(DemoContext *ctx)
191191 }
192192 }
193193
194+ /* Periodic particle bursts from center */
195+ static float last_burst_time = -999.0f ;
196+ static int burst_style = 0 ;
197+ float burst_interval = 2.5f ; /* Burst every 2.5 seconds */
198+ int cx = WIDTH / 2 ;
199+ int cy = HEIGHT / 2 ;
200+
201+ /* Trigger new burst periodically */
202+ if (ctx -> global_time - last_burst_time > burst_interval ) {
203+ last_burst_time = ctx -> global_time ;
204+ burst_style = (burst_style + 1 ) % 3 ; /* Cycle through 3 styles */
205+ }
206+
207+ float time_since_burst = ctx -> global_time - last_burst_time ;
208+
209+ /* Only draw particles during active burst (first 2 seconds) */
210+ if (time_since_burst < 2.0f ) {
211+ int num_particles = 80 ;
212+
213+ for (int i = 0 ; i < num_particles ; i ++ ) {
214+ float angle , radius , px_f , py_f ;
215+ int px , py , r , g , b ;
216+ float life = 1.0f - (time_since_burst / 2.0f );
217+ if (life < 0.0f ) life = 0.0f ;
218+
219+ if (burst_style == 0 ) {
220+ /* Style 0: Radial explosion (rainbow) */
221+ angle = (i / (float )num_particles ) * 2 * PI ;
222+ float speed = 150.0f + (i % 20 ) * 10.0f ;
223+ radius = speed * time_since_burst ;
224+ px = cx + (int )(radius * cosf (angle ));
225+ py = cy + (int )(radius * sinf (angle ));
226+
227+ float hue = angle / (2 * PI );
228+ r = (int )(255 * life * (0.5f + 0.5f * sinf (hue * 2 * PI )));
229+ g = (int )(255 * life * (0.5f + 0.5f * sinf (hue * 2 * PI + 2 * PI / 3 )));
230+ b = (int )(255 * life * (0.5f + 0.5f * sinf (hue * 2 * PI + 4 * PI / 3 )));
231+ } else if (burst_style == 1 ) {
232+ /* Style 1: Spiral outward (cyan/blue) */
233+ angle = (i / (float )num_particles ) * 2 * PI ;
234+ float spiral_speed = 100.0f ;
235+ radius = spiral_speed * time_since_burst ;
236+ float spiral_rotation = time_since_burst * 3.0f ; /* Spiral effect */
237+ px = cx + (int )(radius * cosf (angle + spiral_rotation ));
238+ py = cy + (int )(radius * sinf (angle + spiral_rotation ));
239+
240+ r = (int )(100 * life );
241+ g = (int )(220 * life );
242+ b = (int )(255 * life );
243+ } else {
244+ /* Style 2: Ring expansion (orange/red) */
245+ angle = (i / (float )num_particles ) * 2 * PI ;
246+ /* Multiple concentric rings */
247+ int ring = i % 4 ;
248+ float ring_delay = ring * 0.15f ;
249+ float ring_time = time_since_burst - ring_delay ;
250+ if (ring_time < 0.0f ) ring_time = 0.0f ;
251+
252+ radius = 120.0f * ring_time ;
253+ px = cx + (int )(radius * cosf (angle ));
254+ py = cy + (int )(radius * sinf (angle ));
255+
256+ /* Adjust life based on ring delay */
257+ float ring_life = 1.0f - (ring_time / 1.8f );
258+ if (ring_life < 0.0f ) ring_life = 0.0f ;
259+
260+ r = (int )(255 * ring_life );
261+ g = (int )(150 * ring_life );
262+ b = (int )(50 * ring_life );
263+ }
264+
265+ /* Draw particle with glow */
266+ for (int dy = -2 ; dy <= 2 ; dy ++ ) {
267+ for (int dx = -2 ; dx <= 2 ; dx ++ ) {
268+ int x = px + dx ;
269+ int y = py + dy ;
270+
271+ if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT ) {
272+ float dist = sqrtf (dx * dx + dy * dy );
273+ if (dist <= 2.0f ) {
274+ float glow = (1.0f - dist / 2.0f ) * 0.7f ;
275+
276+ int pr = (int )(r * glow );
277+ int pg = (int )(g * glow );
278+ int pb = (int )(b * glow );
279+
280+ /* Blend with existing pixel */
281+ Uint32 existing = ctx -> pixels [y * WIDTH + x ];
282+ int er = (existing >> 16 ) & 0xFF ;
283+ int eg = (existing >> 8 ) & 0xFF ;
284+ int eb = existing & 0xFF ;
285+
286+ int nr = (pr + er > 255 ) ? 255 : pr + er ;
287+ int ng = (pg + eg > 255 ) ? 255 : pg + eg ;
288+ int nb = (pb + eb > 255 ) ? 255 : pb + eb ;
289+
290+ ctx -> pixels [y * WIDTH + x ] = 0xFF000000 | (nr << 16 ) | (ng << 8 ) | nb ;
291+ }
292+ }
293+ }
294+ }
295+ }
296+ }
297+
194298 /* Update texture */
195299 SDL_UpdateTexture (ctx -> texture , NULL , ctx -> pixels , WIDTH * sizeof (Uint32 ));
196300 SDL_RenderClear (ctx -> renderer );
0 commit comments