@@ -122,6 +122,46 @@ static void update_particles(AnimState *state, double dt)
122122 }
123123}
124124
125+ static void update_streaks (AnimState * state , double dt )
126+ {
127+ /* Wind streaks appear above ~5 m/s, scale up to max at ~15 m/s */
128+ double wind_ms = state -> weather .windspeed / 3.6 ;
129+ int target = 0 ;
130+
131+ if (wind_ms >= 5.0 ) {
132+ double frac = (wind_ms - 5.0 ) / 10.0 ;
133+
134+ if (frac > 1.0 ) frac = 1.0 ;
135+ target = (int )(frac * ANIM_MAX_STREAKS );
136+ if (target < 1 ) target = 1 ;
137+ }
138+
139+ while (state -> streak_count < target ) {
140+ Particle * s = & state -> streaks [state -> streak_count ];
141+
142+ s -> x = - randf () * state -> width * 0.3 ;
143+ s -> y = randf () * state -> height ;
144+ s -> speed = 150.0 + wind_ms * 20.0 + randf () * 100.0 ;
145+ s -> size = 30.0 + randf () * 50.0 ; /* streak length */
146+ state -> streak_count ++ ;
147+ }
148+
149+ if (state -> streak_count > target )
150+ state -> streak_count = target ;
151+
152+ for (int i = 0 ; i < state -> streak_count ; i ++ ) {
153+ Particle * s = & state -> streaks [i ];
154+
155+ s -> x += s -> speed * dt ;
156+
157+ if (s -> x > state -> width + s -> size ) {
158+ s -> x = - s -> size - randf () * state -> width * 0.2 ;
159+ s -> y = randf () * state -> height ;
160+ s -> speed = 150.0 + wind_ms * 20.0 + randf () * 100.0 ;
161+ }
162+ }
163+ }
164+
125165void anim_update (AnimState * state , double dt , const WeatherData * weather )
126166{
127167 state -> weather = * weather ;
@@ -130,6 +170,7 @@ void anim_update(AnimState *state, double dt, const WeatherData *weather)
130170
131171 update_clouds (state , dt );
132172 update_particles (state , dt );
173+ update_streaks (state , dt );
133174}
134175
135176/* ------------------------------------------------------------------ */
@@ -265,11 +306,38 @@ static void draw_snow(const AnimState *state, cairo_t *cr)
265306 }
266307}
267308
309+ static void draw_streaks (const AnimState * state , cairo_t * cr )
310+ {
311+ if (state -> streak_count == 0 )
312+ return ;
313+
314+ cairo_set_line_width (cr , 1.0 );
315+
316+ for (int i = 0 ; i < state -> streak_count ; i ++ ) {
317+ const Particle * s = & state -> streaks [i ];
318+ /* Fade in/out at edges */
319+ double alpha = 0.12 + 0.06 * sin (state -> time_accum * 1.5 + i );
320+
321+ cairo_pattern_t * grad = cairo_pattern_create_linear (
322+ s -> x - s -> size , s -> y , s -> x , s -> y );
323+ cairo_pattern_add_color_stop_rgba (grad , 0.0 , 1.0 , 1.0 , 1.0 , 0.0 );
324+ cairo_pattern_add_color_stop_rgba (grad , 0.3 , 1.0 , 1.0 , 1.0 , alpha );
325+ cairo_pattern_add_color_stop_rgba (grad , 1.0 , 1.0 , 1.0 , 1.0 , 0.0 );
326+
327+ cairo_move_to (cr , s -> x - s -> size , s -> y );
328+ cairo_line_to (cr , s -> x , s -> y );
329+ cairo_set_source (cr , grad );
330+ cairo_stroke (cr );
331+ cairo_pattern_destroy (grad );
332+ }
333+ }
334+
268335void anim_draw (const AnimState * state , cairo_t * cr )
269336{
270337 draw_sky (state , cr );
271338 draw_sun (state , cr );
272339 draw_clouds (state , cr );
340+ draw_streaks (state , cr );
273341
274342 bool rain = (state -> weather .type == WEATHER_RAIN ||
275343 state -> weather .type == WEATHER_DRIZZLE ||
0 commit comments