cuqueclicker_lib/ui/
effects.rs1use ratatui::prelude::*;
2
3use crate::game::state::{MisclickParticle, Particle, ParticleKind, biscuit_frac_to_screen};
4
5const PARTICLE_LIFE_F: f32 = 20.0;
6const MISCLICK_LIFE_F: f32 = 8.0;
7
8pub fn draw_particles(frame: &mut Frame, biscuit: Rect, particles: &[Particle]) {
13 if biscuit.width == 0 || biscuit.height == 0 {
14 return;
15 }
16 let buf = frame.buffer_mut();
17 for p in particles {
18 let (col, row) = biscuit_frac_to_screen(p.frac_x, p.frac_y, biscuit);
19 if row < biscuit.y || row >= biscuit.y + biscuit.height {
20 continue;
21 }
22 if col < biscuit.x || col >= biscuit.x + biscuit.width {
23 continue;
24 }
25 let t = (p.life as f32 / PARTICLE_LIFE_F).clamp(0.0, 1.0);
26 let style = particle_style(p.kind, t);
27 buf.set_string(col, row, &p.text, style);
28 }
29}
30
31fn particle_style(kind: ParticleKind, t: f32) -> Style {
35 let dim = (t * 255.0) as u8;
36 match kind {
37 ParticleKind::Click | ParticleKind::Auto => Style::default()
39 .fg(Color::Rgb(255, dim, dim))
40 .add_modifier(Modifier::BOLD),
41 ParticleKind::ClickBig => Style::default()
44 .fg(Color::Rgb(255, 255 - (255 - dim) / 2, dim))
45 .add_modifier(Modifier::BOLD),
46 ParticleKind::Golden => Style::default()
48 .fg(Color::Rgb(255, 230, (dim / 2).max(80)))
49 .add_modifier(Modifier::BOLD),
50 ParticleKind::Confetti => Style::default()
53 .fg(Color::Rgb(((1.0 - t) * 200.0) as u8 + 55, dim, 255))
54 .add_modifier(Modifier::BOLD),
55 }
56}
57
58pub fn draw_misclicks(frame: &mut Frame, particles: &[MisclickParticle]) {
62 let buf = frame.buffer_mut();
63 let area = buf.area;
64 for m in particles {
65 if m.col < area.x
66 || m.col >= area.x + area.width
67 || m.row < area.y
68 || m.row >= area.y + area.height
69 {
70 continue;
71 }
72 let t = (m.life as f32 / MISCLICK_LIFE_F).clamp(0.0, 1.0);
73 let v = (t * 180.0) as u8 + 60;
74 let style = Style::default().fg(Color::Rgb(v, v, v));
75 buf.set_string(m.col, m.row, "·", style);
76 }
77}