1use rand::{Rng, SeedableRng};
2
3pub const FIRE_WIDTH: usize = 320;
4pub const FIRE_HEIGHT: usize = 168;
5pub const TARGET_FPS: u64 = 60;
6pub const TIME_PER_FRAME: u64 = 1000 / TARGET_FPS; const PALLET: [[u8; 4]; 37] = [
10 [0x07, 0x07, 0x07, 0xFF],
11 [0x1F, 0x07, 0x07, 0xFF],
12 [0x2F, 0x0F, 0x07, 0xFF],
13 [0x47, 0x0F, 0x07, 0xFF],
14 [0x57, 0x17, 0x07, 0xFF],
15 [0x67, 0x1F, 0x07, 0xFF],
16 [0x77, 0x1F, 0x07, 0xFF],
17 [0x8F, 0x27, 0x07, 0xFF],
18 [0x9F, 0x2F, 0x07, 0xFF],
19 [0xAF, 0x3F, 0x07, 0xFF],
20 [0xBF, 0x47, 0x07, 0xFF],
21 [0xC7, 0x47, 0x07, 0xFF],
22 [0xDF, 0x4F, 0x07, 0xFF],
23 [0xDF, 0x57, 0x07, 0xFF],
24 [0xDF, 0x57, 0x07, 0xFF],
25 [0xD7, 0x5F, 0x07, 0xFF],
26 [0xD7, 0x5F, 0x07, 0xFF],
27 [0xD7, 0x67, 0x0F, 0xFF],
28 [0xCF, 0x6F, 0x0F, 0xFF],
29 [0xCF, 0x77, 0x0F, 0xFF],
30 [0xCF, 0x7F, 0x0F, 0xFF],
31 [0xCF, 0x87, 0x17, 0xFF],
32 [0xC7, 0x87, 0x17, 0xFF],
33 [0xC7, 0x8F, 0x17, 0xFF],
34 [0xC7, 0x97, 0x1F, 0xFF],
35 [0xBF, 0x9F, 0x1F, 0xFF],
36 [0xBF, 0x9F, 0x1F, 0xFF],
37 [0xBF, 0xA7, 0x27, 0xFF],
38 [0xBF, 0xA7, 0x27, 0xFF],
39 [0xBF, 0xAF, 0x2F, 0xFF],
40 [0xB7, 0xAF, 0x2F, 0xFF],
41 [0xB7, 0xB7, 0x2F, 0xFF],
42 [0xB7, 0xB7, 0x37, 0xFF],
43 [0xCF, 0xCF, 0x6F, 0xFF],
44 [0xDF, 0xDF, 0x9F, 0xFF],
45 [0xEF, 0xEF, 0xC7, 0xFF],
46 [0xFF, 0xFF, 0xFF, 0xFF],
47];
48
49pub struct DoomFire {
50 fire_pixels: Vec<usize>,
51}
52
53impl DoomFire {
54 pub fn new() -> Self {
55 let mut fire_pixels = vec![0; FIRE_WIDTH * FIRE_HEIGHT];
57 for i in 0..FIRE_WIDTH {
59 fire_pixels[(FIRE_HEIGHT - 1) * FIRE_WIDTH + i] = 36;
60 }
61
62 DoomFire { fire_pixels }
63 }
64
65 pub fn update(&mut self) {
68 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(666);
72
73 for x in 0..FIRE_WIDTH {
74 for y in 1..FIRE_HEIGHT {
75 let src = y * FIRE_WIDTH + x;
76 let pixel = self.fire_pixels[src];
77
78 if pixel == 0 {
79 self.fire_pixels[src - FIRE_WIDTH] = 0;
80 } else {
81 let rand_idx = (rng.gen_range(0.0, 3.0) + 0.5) as usize & 3;
82 let dst = src - rand_idx + 1;
83 self.fire_pixels[dst - FIRE_WIDTH] = pixel - (rand_idx & 1);
84 }
85 }
86 }
87 }
88
89 pub fn draw(&self, frame: &mut [u8]) {
93 for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
94 pixel.copy_from_slice(&PALLET[self.fire_pixels[i]])
95 }
96 }
97}
98
99impl Default for DoomFire {
100 fn default() -> Self {
101 DoomFire::new()
102 }
103}