Skip to main content

sl/
smoke.rs

1use std::collections::VecDeque;
2use std::sync::atomic::{AtomicUsize, Ordering};
3
4static SMOKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
5
6#[derive(Clone, Copy)]
7pub struct Particle {
8    pub x: i32,
9    pub y: i32,
10    pub pattern: usize,
11    pub kind: usize,
12}
13
14pub struct Smoke {
15    particles: VecDeque<Particle>,
16    should_generate: bool,
17}
18
19thread_local! {
20    static SMOKE: std::cell::RefCell<Smoke> = const {
21        std::cell::RefCell::new(Smoke {
22            particles: VecDeque::new(),
23            should_generate: false,
24        })
25    };
26}
27
28pub fn set_generation_gate(should_gen: bool) {
29    SMOKE.with(|s| {
30        let mut smoke = s.borrow_mut();
31        smoke.should_generate = should_gen;
32    });
33}
34
35pub fn add_smoke(x: i32, y: i32) {
36    SMOKE.with(|s| {
37        let mut smoke = s.borrow_mut();
38        if smoke.should_generate && smoke.particles.len() < 1000 {
39            let counter = SMOKE_COUNTER.fetch_add(1, Ordering::SeqCst);
40            let kind = counter % 2;
41            smoke.particles.push_back(Particle {
42                x,
43                y,
44                pattern: 0,
45                kind,
46            });
47        }
48    });
49}
50
51pub fn update_smoke() {
52    SMOKE.with(|s| {
53        let mut smoke = s.borrow_mut();
54        if !smoke.should_generate {
55            return;
56        }
57        for particle in &mut smoke.particles {
58            use crate::train::ascii::{SMOKE_DX, SMOKE_DY};
59
60            let dy = SMOKE_DY[particle.pattern];
61            let dx = SMOKE_DX[particle.pattern];
62
63            particle.y -= dy;
64            particle.x += dx;
65            particle.pattern += 1;
66        }
67        smoke.particles.retain(|p| p.pattern < 16);
68    });
69}
70
71pub fn get_smoke_particles() -> Vec<Particle> {
72    SMOKE.with(|s| {
73        let smoke = s.borrow();
74        smoke.particles.iter().copied().collect()
75    })
76}
77
78pub fn clear_smoke() {
79    SMOKE.with(|s| {
80        let mut smoke = s.borrow_mut();
81        smoke.particles.clear();
82    });
83}