11 releases
0.2.1 | Nov 18, 2024 |
---|---|
0.2.0 | Nov 12, 2024 |
0.1.8 | Nov 12, 2024 |
0.1.7 | Oct 10, 2024 |
#4 in #graphical
392 downloads per month
21KB
285 lines
Chinchilib
A rust hommage to the Bunny Library designed for teaching the fundamentals of graphical programming, such as how to place a pixel and draw lines when given an array of memory that will rendered to screen.
It's mostly a wrapper arround pixels and winit that takes care of refresh rate, and keeps track of a set of pressed keys.
Usage
WinitHandler
creates a window for you and manages events and timing. You can package your code into a chinchilib::GfxApp
implementing struct such as MovingPixel
in the example bellow.
WinitHandler
will make calls to:
on_tick
when its time for updating your state with the keys that are pressed right now (or have been pressed in between ticks), returntrue
when you wantdraw
to be called afterwards;draw
when its time to modify the framebuffer so that the image on screen changes;done
when it wants to know if your app has anything left to do:NotDone
is self-explanatory,Remain
means that your app is done, but you want the result to stay on screen until the user exits,Exit
means that your app is done and the window should close.
WinitHandler
closes the window when the user presses the close button or the escape key.
use chinchilib::pixels::Pixels;
use chinchilib::rgb;
use chinchilib::{put_pixel, GfxApp, Key, WinitHandler};
fn main() {
env_logger::init();
log::info!("Hello, world!");
let moving_pixel = Box::new(MovingPixel::new(50, 100));
let mut app = WinitHandler::new(moving_pixel, (500, 500), 60);
// We don't have any physics or animations, false helps to preserve performance.
app.set_always_tick(false);
app.run().unwrap();
}
/// Example app that only feature a pixel that moves.
struct MovingPixel {
pos: (usize, usize),
}
impl Default for MovingPixel {
fn default() -> Self {
Self { pos: (0, 0) }
}
}
impl MovingPixel {
fn new(x: usize, y: usize) -> Self {
Self { pos: (x, y) }
}
}
const RED: rgb::RGBA8 = rgb::RGBA8 {
r: u8::MAX,
g: 0,
b: 0,
a: u8::MAX,
};
impl GfxApp for MovingPixel {
fn on_tick(&mut self, pressed_keys: &std::collections::HashSet<Key>) -> bool {
let mut needs_redraw = true;
for key in pressed_keys {
match key {
Key::Left => {
self.pos.0 -= 1;
}
Key::Right => {
self.pos.0 += 1;
}
Key::Up => {
self.pos.1 -= 1;
}
Key::Down => {
self.pos.1 += 1;
}
_ => {
needs_redraw = false;
}
}
}
needs_redraw
}
fn draw(&self, pixels: &mut Pixels, width: usize) {
if self.pos.0 * self.pos.1 < pixels.frame().len() {
put_pixel(pixels.frame_mut(), width, self.pos.0, self.pos.1, RED);
}
}
/// For the sake of the example, when x goes under 50, we inidcate that we are done and that
/// the windows should remain open, when y goes under 50 we indicate that the window should
/// close, otherwise we are not done.
fn done(&self) -> chinchilib::DoneStatus {
if self.pos.0 < 50 {
chinchilib::DoneStatus::Remain
} else if self.pos.1 < 50 {
chinchilib::DoneStatus::Exit
} else {
chinchilib::DoneStatus::NotDone
}
}
}
Dependencies
~7–43MB
~721K SLoC