1use std::{
4 f32::consts::PI,
5 time::{Duration, SystemTime},
6};
7
8use glam::Vec2;
9use rand::{seq::IteratorRandom, thread_rng, Rng};
10
11use crate::{
12 config::Config,
13 fireworks::{ExplosionForm, Firework, FireworkConfig},
14 particle::ParticleConfig,
15 utils::{
16 explosion_gradient_1, explosion_gradient_2, explosion_gradient_3, gen_points_arc,
17 gen_points_circle, gen_points_circle_normal, gen_points_circle_normal_dev, gen_points_fan,
18 linear_gradient_1,
19 },
20};
21
22pub fn demo_firework_0(
23 center: Vec2,
24 spawn_after: Duration,
25 enable_gradient: bool,
26 colors: Vec<(u8, u8, u8)>,
27 cfg: &Config,
28) -> Firework {
29 let mut particles = Vec::new();
30 for v in gen_points_circle_normal(
31 thread_rng().gen_range(if cfg.enable_cjk {
32 400.0..600.0
33 } else {
34 230.0..400.0
35 }),
36 thread_rng().gen_range(if cfg.enable_cjk { 20..35 } else { 33..47 }),
37 )
38 .iter()
39 {
40 particles.push(ParticleConfig::new(
41 center,
42 *v,
43 thread_rng().gen_range(20..25),
44 Duration::from_secs_f32(thread_rng().gen_range(1.8..2.3)),
45 *colors.iter().choose(&mut thread_rng()).unwrap(),
46 ));
47 }
48 let mut config = FireworkConfig::default().with_gradient_scale(explosion_gradient_1);
49 config.set_enable_gradient(enable_gradient);
50 Firework {
51 init_time: SystemTime::now(),
52 spawn_after,
53 center,
54 particles,
55 config,
56 ..Default::default()
57 }
58}
59
60pub fn demo_firework_1(center: Vec2, spawn_after: Duration, enable_gradient: bool) -> Firework {
61 let colors = [
62 (255, 102, 75),
63 (144, 56, 67),
64 (255, 225, 124),
65 (206, 32, 41),
66 ];
67 let mut particles = Vec::new();
68 for v in gen_points_circle_normal(250., 45).iter() {
69 particles.push(ParticleConfig::new(
70 center,
71 *v,
72 thread_rng().gen_range(23..27),
73 Duration::from_secs_f32(thread_rng().gen_range(2.1..2.7)),
74 *colors.iter().choose(&mut thread_rng()).unwrap(),
75 ));
76 }
77 let mut config = FireworkConfig::default().with_gradient_scale(explosion_gradient_1);
78 config.set_enable_gradient(enable_gradient);
79 Firework {
80 init_time: SystemTime::now(),
81 spawn_after,
82 center,
83 particles,
84 config,
85 ..Default::default()
86 }
87}
88
89pub fn demo_firework_2(center: Vec2, spawn_after: Duration, enable_gradient: bool) -> Firework {
90 let colors = [(250, 216, 68)];
91 let mut particles = Vec::new();
92 for v in gen_points_circle(100, 600).iter() {
93 particles.push(ParticleConfig::new(
94 center,
95 *v,
96 thread_rng().gen_range(5..8),
97 Duration::from_secs_f32(thread_rng().gen_range(3.0..5.5)),
98 *colors.iter().choose(&mut thread_rng()).unwrap(),
99 ));
100 }
101 let mut config = FireworkConfig::default()
102 .with_gradient_scale(explosion_gradient_2)
103 .with_gravity_scale(0.)
104 .with_ar_scale(0.15);
105 config.set_enable_gradient(enable_gradient);
106 Firework {
107 init_time: SystemTime::now(),
108 spawn_after,
109 center,
110 particles,
111 config,
112 ..Default::default()
113 }
114}
115
116pub fn demo_firework_3(center: Vec2, spawn_after: Duration, enable_gradient: bool) -> Firework {
117 let colors = [
118 (242, 233, 190),
119 (226, 196, 136),
120 (149, 202, 176),
121 (26, 64, 126),
122 ];
123 let mut particles = Vec::new();
124 for v in gen_points_circle_normal(350., 135).iter() {
125 particles.push(ParticleConfig::new(
126 center,
127 *v,
128 thread_rng().gen_range(23..43),
129 Duration::from_secs_f32(thread_rng().gen_range(3.5..5.0)),
130 *colors.iter().choose(&mut thread_rng()).unwrap(),
131 ));
132 }
133 let mut config = FireworkConfig::default()
134 .with_gradient_scale(explosion_gradient_1)
135 .with_ar_scale(0.18)
136 .with_gravity_scale(0.7);
137 config.set_enable_gradient(enable_gradient);
138 Firework {
139 init_time: SystemTime::now(),
140 spawn_after,
141 center,
142 particles,
143 config,
144 ..Default::default()
145 }
146}
147
148pub fn demo_firework_4(center: Vec2, spawn_after: Duration, enable_gradient: bool) -> Firework {
149 let colors = [(242, 233, 190), (226, 196, 136), (255, 248, 253)];
150 let mut particles = Vec::new();
151 for v in gen_points_circle_normal(350., 25).iter() {
152 particles.push(ParticleConfig::new(
153 center,
154 *v,
155 thread_rng().gen_range(20..33),
156 Duration::from_secs_f32(thread_rng().gen_range(3.5..5.0)),
157 *colors.iter().choose(&mut thread_rng()).unwrap(),
158 ));
159 }
160 let mut config = FireworkConfig::default()
161 .with_gradient_scale(explosion_gradient_1)
162 .with_gravity_scale(0.3);
163 config.set_enable_gradient(enable_gradient);
164 Firework {
165 init_time: SystemTime::now(),
166 spawn_after,
167 center,
168 particles,
169 config,
170 ..Default::default()
171 }
172}
173
174pub fn demo_firework_5(center: Vec2, spawn_after: Duration, enable_gradient: bool) -> Firework {
175 let colors = [(152, 186, 227), (54, 84, 117), (21, 39, 60)];
176 let mut particles = Vec::new();
177 for v in gen_points_circle_normal(450., 80).iter() {
178 particles.push(ParticleConfig::new(
179 center,
180 *v,
181 thread_rng().gen_range(33..43),
182 Duration::from_secs_f32(thread_rng().gen_range(3.5..5.0)),
183 *colors.iter().choose(&mut thread_rng()).unwrap(),
184 ));
185 }
186 let mut config = FireworkConfig::default()
187 .with_gradient_scale(explosion_gradient_3)
188 .with_gravity_scale(1.4);
189 config.set_enable_gradient(enable_gradient);
190 Firework {
191 init_time: SystemTime::now(),
192 spawn_after,
193 center,
194 particles,
195 config,
196 ..Default::default()
197 }
198}
199
200pub fn demo_firework_6(center: Vec2, spawn_after: Duration, enable_gradient: bool) -> Firework {
201 let colors = [(242, 233, 190), (226, 196, 136), (255, 248, 253)];
202 let mut particles = Vec::new();
203 for v in gen_points_circle_normal(350., 35).iter() {
204 particles.push(ParticleConfig::new(
205 center,
206 *v,
207 thread_rng().gen_range(20..23),
208 Duration::from_secs_f32(thread_rng().gen_range(3.5..4.0)),
209 *colors.iter().choose(&mut thread_rng()).unwrap(),
210 ));
211 }
212 let mut config = FireworkConfig::default()
213 .with_gradient_scale(explosion_gradient_1)
214 .with_ar_scale(0.19)
215 .with_gravity_scale(0.1);
216 config.set_enable_gradient(enable_gradient);
217 Firework {
218 init_time: SystemTime::now(),
219 spawn_after,
220 center,
221 particles,
222 config,
223 ..Default::default()
224 }
225}
226
227pub fn demo_firework_comb_1(
228 start: Vec2,
229 spawn_after: Duration,
230 enable_gradient: bool,
231) -> Vec<Firework> {
232 let color1 = (255, 255, 235);
234 let particles1 = ParticleConfig::new(
235 start,
236 Vec2::NEG_Y * 160.,
237 6,
238 Duration::from_secs_f32(1.2),
239 color1,
240 );
241 let mut config1 = FireworkConfig::default()
242 .with_ar_scale(0.04)
243 .with_gradient_scale(linear_gradient_1);
244 config1.set_enable_gradient(enable_gradient);
245
246 let color2 = [
248 (235, 39, 155),
249 (250, 216, 68),
250 (242, 52, 72),
251 (63, 52, 200),
252 (255, 139, 57),
253 ];
254 let center2 = start + Vec2::NEG_Y * 53.;
255 let mut particles2 = Vec::new();
256 for v in gen_points_circle_normal(350., 160).iter() {
257 particles2.push(ParticleConfig::new(
258 center2,
259 *v,
260 thread_rng().gen_range(23..43),
261 Duration::from_secs_f32(thread_rng().gen_range(2.5..4.5)),
262 *color2.iter().choose(&mut thread_rng()).unwrap(),
263 ));
264 }
265 let mut config2 = FireworkConfig::default()
266 .with_gradient_scale(explosion_gradient_1)
267 .with_ar_scale(0.2)
268 .with_gravity_scale(0.3);
269 config2.set_enable_gradient(enable_gradient);
270 vec![
271 Firework {
272 init_time: SystemTime::now(),
273 spawn_after,
274 center: start,
275 particles: vec![particles1],
276 config: config1,
277 ..Default::default()
278 },
279 Firework {
280 init_time: SystemTime::now(),
281 spawn_after: spawn_after + Duration::from_secs_f32(1.2),
282 center: center2,
283 particles: particles2,
284 config: config2,
285 ..Default::default()
286 },
287 ]
288}
289
290pub fn demo_firework_comb_0(
291 center: Vec2,
292 spawn_after: Duration,
293 enable_gradient: bool,
294) -> Vec<Firework> {
295 vec![
296 demo_firework_3(center + Vec2::new(-5., -19.), spawn_after, enable_gradient),
297 demo_firework_4(
298 center + Vec2::new(-30., 0.),
299 spawn_after + Duration::from_secs_f32(0.4),
300 enable_gradient,
301 ),
302 demo_firework_5(
303 center + Vec2::new(12., 0.),
304 spawn_after + Duration::from_secs_f32(1.6),
305 enable_gradient,
306 ),
307 demo_firework_1(
308 center + Vec2::new(-9., 7.),
309 spawn_after + Duration::from_secs_f32(2.),
310 enable_gradient,
311 ),
312 demo_firework_6(
313 center + Vec2::new(24., -11.),
314 spawn_after + Duration::from_secs_f32(2.3),
315 enable_gradient,
316 ),
317 ]
318}
319
320pub fn demo_firework_comb_2(
321 center: Vec2,
322 spawn_after: Duration,
323 enable_gradient: bool,
324) -> Vec<Firework> {
325 let mut res = Vec::new();
326 let fountain1 = |center: Vec2, angle: f32| {
327 let colors = [(255, 183, 3), (251, 133, 0), (242, 233, 190)];
328 let mut particles = Vec::new();
329 for v in gen_points_fan(60., 20, angle - 0.05, angle + 0.05).iter() {
330 particles.push(ParticleConfig::new(
331 center,
332 *v,
333 thread_rng().gen_range(28..38),
334 Duration::from_secs_f32(thread_rng().gen_range(2.5..3.8)),
335 *colors.iter().choose(&mut thread_rng()).unwrap(),
336 ));
337 }
338 let mut config = FireworkConfig::default()
339 .with_ar_scale(0.05)
340 .with_gradient_scale(linear_gradient_1);
341 config.set_enable_gradient(enable_gradient);
342 Firework {
343 init_time: SystemTime::now(),
344 spawn_after,
345 center,
346 particles,
347 config,
348 form: ExplosionForm::Sustained {
349 lasts: Duration::from_secs(5),
350 time_interval: Duration::from_secs_f32(0.08),
351 timer: Duration::ZERO,
352 },
353 ..Default::default()
354 }
355 };
356
357 let fountain2 = |center: Vec2| {
358 let colors = [(226, 196, 136), (255, 245, 253), (208, 58, 99)];
359 let mut particles = Vec::new();
360 for v in gen_points_fan(1000., 20, 5.7 / 12. * PI, 6.3 / 12. * PI).iter() {
361 particles.push(ParticleConfig::new(
362 center,
363 *v,
364 thread_rng().gen_range(28..38),
365 Duration::from_secs_f32(thread_rng().gen_range(2.5..3.8)),
366 *colors.iter().choose(&mut thread_rng()).unwrap(),
367 ));
368 }
369 let mut config = FireworkConfig::default()
370 .with_ar_scale(0.14)
371 .with_gravity_scale(0.9)
372 .with_gradient_scale(linear_gradient_1);
373 config.set_enable_gradient(enable_gradient);
374 Firework {
375 init_time: SystemTime::now(),
376 spawn_after: spawn_after + Duration::from_secs_f32(4.),
377 center,
378 particles,
379 config,
380 form: ExplosionForm::Sustained {
381 lasts: Duration::from_secs(5),
382 time_interval: Duration::from_secs_f32(0.08),
383 timer: Duration::ZERO,
384 },
385 ..Default::default()
386 }
387 };
388
389 let mono = |center: Vec2, sa: Duration, colors: Vec<(u8, u8, u8)>| {
390 let particles = vec![ParticleConfig::new(
391 center,
392 gen_points_arc(200., 1, 5. / 12. * PI, 7. / 12. * PI)[0],
393 thread_rng().gen_range(24..30),
394 Duration::from_secs_f32(thread_rng().gen_range(2.1..2.7)),
395 *colors.iter().choose(&mut thread_rng()).unwrap(),
396 )];
397 let mut config = FireworkConfig::default()
398 .with_ar_scale(thread_rng().gen_range(0.18..0.24))
399 .with_gradient_scale(linear_gradient_1);
400 config.set_enable_gradient(enable_gradient);
401 Firework {
402 init_time: SystemTime::now(),
403 spawn_after: sa,
404 center,
405 particles,
406 config,
407 form: ExplosionForm::Instant { used: false },
408 ..Default::default()
409 }
410 };
411
412 res.push(fountain1(center + Vec2::new(-31., 21.), 1.05));
413 res.push(fountain1(center + Vec2::new(31., 21.), 2.09));
414
415 res.push(fountain2(center + Vec2::new(-7., 21.)));
416 res.push(fountain2(center + Vec2::new(7., 21.)));
417
418 (-33..=33).step_by(3).for_each(|i| {
419 res.push(mono(
420 Vec2::new(center.x + i as f32, center.y + 21.),
421 Duration::from_secs_f32(3.5),
422 vec![(0, 119, 182), (144, 224, 239), (12, 180, 216)],
423 ))
424 });
425
426 (-33..=33).step_by(3).for_each(|i| {
427 res.push(mono(
428 Vec2::new(center.x + i as f32, center.y + 21.),
429 Duration::from_secs_f32(4.7),
430 vec![(181, 23, 158), (247, 37, 133), (114, 9, 183)],
431 ))
432 });
433
434 (-33..=33).step_by(3).for_each(|i| {
435 res.push(mono(
436 Vec2::new(center.x + i as f32, center.y + 21.),
437 Duration::from_secs_f32(5.9),
438 vec![(217, 237, 146), (153, 217, 140), (82, 182, 154)],
439 ))
440 });
441
442 res
443}
444
445pub fn demo_firework_comb_3(
446 center: Vec2,
447 spawn_after: Duration,
448 enable_gradient: bool,
449) -> Vec<Firework> {
450 let mut res = Vec::new();
451 let f1 = {
452 let colors = [(255, 216, 190), (255, 238, 221), (248, 247, 255)];
453 let mut particles = Vec::new();
454 for v in gen_points_circle_normal_dev(14., 200, 60.).iter() {
455 particles.push(ParticleConfig::new(
456 center + Vec2::NEG_Y * 6.,
457 *v,
458 thread_rng().gen_range(15..20),
459 Duration::from_secs_f32(thread_rng().gen_range(3.0..5.0)),
460 *colors.iter().choose(&mut thread_rng()).unwrap(),
461 ));
462 }
463 let mut config = FireworkConfig::default()
464 .with_gradient_scale(explosion_gradient_1)
465 .with_ar_scale(0.15)
466 .with_gravity_scale(0.35);
467 config.set_enable_gradient(enable_gradient);
468 Firework {
469 init_time: SystemTime::now(),
470 spawn_after,
471 center,
472 particles,
473 config,
474 ..Default::default()
475 }
476 };
477 res.push(f1);
478 let f2 = {
479 let colors = [
480 (152, 186, 227),
481 (89, 129, 177),
482 (54, 84, 117),
483 (240, 244, 254),
484 ];
485 let mut particles = Vec::new();
486 for v in gen_points_circle_normal_dev(10000., 600, 30.).iter() {
487 particles.push(ParticleConfig::new(
488 center + Vec2::NEG_Y * 6.,
489 *v,
490 thread_rng().gen_range(20..28),
491 Duration::from_secs_f32(thread_rng().gen_range(4.8..10.)),
492 *colors.iter().choose(&mut thread_rng()).unwrap(),
493 ));
494 }
495 let mut config = FireworkConfig::default()
496 .with_gradient_scale(explosion_gradient_1)
497 .with_ar_scale(0.09)
498 .with_gravity_scale(0.5);
499 config.set_enable_gradient(enable_gradient);
500 Firework {
501 init_time: SystemTime::now(),
502 spawn_after,
503 center,
504 particles,
505 config,
506 ..Default::default()
507 }
508 };
509 res.push(f2);
510
511 for (idx, p) in gen_points_circle(27, 10).iter().enumerate() {
512 let colors = [(17, 138, 178), (6, 214, 160), (7, 59, 76), (255, 255, 255)];
513 let mut particles = Vec::new();
514 for v in gen_points_circle_normal_dev(100., 35, 350. / 9.).iter() {
515 particles.push(ParticleConfig::new(
516 center + *p,
517 *v,
518 thread_rng().gen_range(20..30),
519 Duration::from_secs_f32(thread_rng().gen_range(3.0..4.0)),
520 *colors.iter().choose(&mut thread_rng()).unwrap(),
521 ));
522 }
523 let mut config = FireworkConfig::default()
524 .with_gradient_scale(explosion_gradient_3)
525 .with_ar_scale(0.28)
526 .with_gravity_scale(0.25);
527 config.set_enable_gradient(enable_gradient);
528 res.push(Firework {
529 init_time: SystemTime::now(),
530 spawn_after: spawn_after + Duration::from_secs_f32(0.2 * (idx + 4) as f32),
531 center,
532 particles,
533 config,
534 ..Default::default()
535 });
536 }
537
538 res
539}