fb/
fb.rs

1use fltk::{app, frame, prelude::*, utils, window::Window};
2
3const WIDTH: i32 = 600;
4const HEIGHT: i32 = 400;
5const CIRCLE_RADIUS: i16 = 64;
6
7struct World {
8    circle_x: i16,
9    circle_y: i16,
10    velocity_x: i16,
11    velocity_y: i16,
12}
13
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    let app = app::App::default();
16    let mut win = Window::default()
17        .with_size(WIDTH, HEIGHT)
18        .with_label("Framebuffer");
19    let mut frame = frame::Frame::default_fill();
20    win.end();
21    win.make_resizable(true);
22    win.show();
23
24    let mut framebuf: Vec<u8> = vec![0; (WIDTH * HEIGHT * 4) as usize];
25    let mut world = World::new();
26
27    unsafe {
28        utils::blit_rgba_nocopy(&mut frame, &framebuf);
29    }
30
31    app::add_idle(move |_| {
32        world.update();
33        world.draw(&mut framebuf);
34        // utils::blit_rgba(&mut frame, &framebuf).unwrap(); // A safe variant of draw_rgba_nocopy
35        win.redraw();
36        // sleeps are necessary when calling redraw in the event loop
37        app::sleep(0.016);
38    });
39
40    app.run()?;
41    Ok(())
42}
43
44impl World {
45    fn new() -> Self {
46        Self {
47            circle_x: 300,
48            circle_y: 200,
49            velocity_x: 5,
50            velocity_y: 5,
51        }
52    }
53
54    fn update(&mut self) {
55        if self.circle_x - CIRCLE_RADIUS <= 0 || self.circle_x + CIRCLE_RADIUS > WIDTH as i16 {
56            self.velocity_x *= -1;
57        }
58        if self.circle_y - CIRCLE_RADIUS <= 0 || self.circle_y + CIRCLE_RADIUS > HEIGHT as i16 {
59            self.velocity_y *= -1;
60        }
61
62        self.circle_x += self.velocity_x;
63        self.circle_y += self.velocity_y;
64    }
65
66    fn draw(&self, frame: &mut [u8]) {
67        for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
68            let x = (i % WIDTH as usize) as i16;
69            let y = (i / WIDTH as usize) as i16;
70            let d = {
71                let xd = x as i32 - self.circle_x as i32;
72                let yd = y as i32 - self.circle_y as i32;
73                ((xd.pow(2) + yd.pow(2)) as f64).sqrt().powi(2)
74            };
75            let inside_the_circle = d < (CIRCLE_RADIUS as f64).powi(2);
76
77            let rgba = if inside_the_circle {
78                [0xac, 0x00, 0xe6, 0xff]
79            } else {
80                [0x26, 0x00, 0x33, 0xff]
81            };
82
83            pixel.copy_from_slice(&rgba);
84        }
85    }
86}