Skip to content

Commit

Permalink
Improved examples
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanoIncardone committed Jan 29, 2024
1 parent d814070 commit b574d4c
Show file tree
Hide file tree
Showing 18 changed files with 338 additions and 296 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ build = "build.rs"
edition = "2018"
readme = "README.md"

exclude = ["resources/"]
exclude = ["examples/resources/"]

[badges]
maintenance = { status = "actively-developed" }
Expand Down
63 changes: 37 additions & 26 deletions examples/char_callback.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,73 @@
use minifb::{Key, Window, WindowOptions};
use std::cell::RefCell;
use std::rc::Rc;
use minifb::{InputCallback, Key, Window, WindowOptions};
use std::{cell::RefCell, rc::Rc};

const WIDTH: usize = 640;
const HEIGHT: usize = 360;
const WIDTH: usize = 1280;
const HEIGHT: usize = 720;

type KeyVec = Rc<RefCell<Vec<u32>>>;

struct Input {
keys: KeyVec,
}

impl Input {
fn new(data: &KeyVec) -> Input {
Input { keys: data.clone() }
}
}

impl minifb::InputCallback for Input {
impl InputCallback for Input {
/// Will be called every time a character key is pressed
fn add_char(&mut self, uni_char: u32) {
self.keys.borrow_mut().push(uni_char);
}
}

fn main() {
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
let mut buffer = vec![0u32; WIDTH * HEIGHT];

let mut window = Window::new(
"Test - ESC to exit",
"char_callback example - press ESC to exit",
WIDTH,
HEIGHT,
WindowOptions::default(),
)
.unwrap_or_else(|e| {
panic!("{:?}", e);
});

let keys_data = KeyVec::new(RefCell::new(Vec::new()));

let input = Box::new(Input::new(&keys_data));
.expect("Unable to create the window");

window.set_target_fps(60);
window.set_input_callback(input);

let keys = KeyVec::new(RefCell::new(Vec::new()));
window.set_input_callback(Box::new(Input { keys: keys.clone() }));

// produces a wave pattern where the screen goes from red to blue, and vice-versa
let mut wave: u8 = 0;
let mut wave_direction: i8 = 1;
while window.is_open() && !window.is_key_down(Key::Escape) {
for i in buffer.iter_mut() {
*i = 0; // write something more funny here!
let red: u32 = (wave as u32) << 16;
let green: u32 = 64 << 8;
let blue: u32 = (255 - wave) as u32;
let bg_color = red | green | blue;

for pixel in buffer.iter_mut() {
*pixel = bg_color;
}

// We unwrap here as we want this code to exit if it fails. Real applications may want to handle this in a different way
window.update_with_buffer(&buffer, WIDTH, HEIGHT).unwrap();

let mut keys = keys_data.borrow_mut();
let mut keys = keys.borrow_mut();

for t in keys.iter() {
println!("Code point: {}, Character: {:?}", *t, char::from_u32(*t));
println!("Code point: {}, Character: {:?}", *t, char::from_u32(*t));
}

keys.clear();

// switch color wave directions
match wave.checked_add_signed(wave_direction) {
Some(new_wave) => wave = new_wave,
None => {
wave_direction = -wave_direction;
if wave_direction > 0 {
wave += 1;
} else {
wave -= 1;
}
}
}
}
}
31 changes: 17 additions & 14 deletions examples/drop.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
use minifb::{Window, WindowOptions};
use std::thread;
use std::time::{Duration, Instant};
use std::{
thread,
time::{Duration, Instant},
};

const WIDTH: usize = 640 / 2;
const HEIGHT: usize = 360 / 2;
const WIDTH: usize = 1280;
const HEIGHT: usize = 720;

fn main() {
println!("Creating and showing a Window");

fn show_window() {
let mut window = Window::new(
"Drop Test - Window will close after 2 seconds.",
"Drop example - Window will close after 5 seconds",
WIDTH,
HEIGHT,
WindowOptions::default(),
)
.expect("Unable to create window");
.expect("Unable to create the window");

let now = Instant::now();
window.set_target_fps(60);

while window.is_open() && now.elapsed().as_secs() < 2 {
let now = Instant::now();
while window.is_open() && now.elapsed().as_secs() < 5 {
window.update();
}
}

fn main() {
println!("Showing Window");
show_window();
drop(window);
println!("Dropped");
thread::sleep(Duration::from_millis(2000));

thread::sleep(Duration::from_secs(2));
println!("Exiting");
}
29 changes: 12 additions & 17 deletions examples/julia.rs → examples/fractal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ const FRACTAL_DEPTH: u32 = 64;
const GENERATION_INFINITY: f64 = 16.;

fn main() {
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
let mut buffer = vec![0u32; WIDTH * HEIGHT];

let mut window = Window::new(
"Fractal - ESC to exit",
"Fractal example - press ESC to exit",
WIDTH,
HEIGHT,
WindowOptions {
resize: true,
scale: Scale::X2,
scale: Scale::X4,
scale_mode: ScaleMode::AspectRatioStretch,
..WindowOptions::default()
},
)
.expect("Unable to Open Window");
.expect("Unable to create the window");

window.set_target_fps(60);

Expand All @@ -39,9 +39,8 @@ fn main() {
let mut real = map((i % WIDTH) as f64, 0., WIDTH as f64, x_min, x_max);
let mut imag = map((i / HEIGHT) as f64, 0., HEIGHT as f64, y_min, y_max);

let mut n = 0;

while n < FRACTAL_DEPTH {
let mut depth = 0;
while depth < FRACTAL_DEPTH {
let re = real.powf(2.) - imag.powf(2.);
let im = 2. * real * imag;

Expand All @@ -51,10 +50,14 @@ fn main() {
if (real + imag).abs() > GENERATION_INFINITY {
break; // Leave when achieve infinity
}
n += 1;
depth += 1;
}

*pixel = fill(n);
*pixel = if depth == FRACTAL_DEPTH {
0x00
} else {
depth * 32 % 255
};
}

angle += 0.1;
Expand All @@ -67,11 +70,3 @@ fn main() {
fn map(val: f64, start1: f64, stop1: f64, start2: f64, stop2: f64) -> f64 {
start2 + (stop2 - start2) * ((val - start1) / (stop1 - start1))
}

fn fill(n: u32) -> u32 {
if FRACTAL_DEPTH == n {
0x00
} else {
n * 32 % 255
}
}
19 changes: 13 additions & 6 deletions examples/icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,25 @@ use std::str::FromStr;

use minifb::{Icon, Key, Window, WindowOptions};

const WIDTH: usize = 1280;
const HEIGHT: usize = 720;

fn main() {
let mut window = Window::new(
"Window Icon Test - Press ESC to exit",
300,
300,
"Window icon example - press ESC to exit",
WIDTH,
HEIGHT,
WindowOptions {
resize: true,
..WindowOptions::default()
},
)
.expect("Unable to open Window");
.expect("Unable to create the window");

window.set_target_fps(60);

#[cfg(target_os = "windows")]
window.set_icon(Icon::from_str("resources/icon256.ico").unwrap());
window.set_icon(Icon::from_str("examples/resources/icon256.ico").unwrap());

#[cfg(target_os = "linux")]
{
Expand Down Expand Up @@ -170,7 +175,9 @@ fn main() {
1476329472, 1342111744, 1207894016, 1056899072, 939458560, 788463616, 654245888,
536281096, 385810432, 251592704, 134152192,
];
window.set_icon(Icon::try_from(&test[..]).unwrap());

// NOTE(@StefanoIncardone): this does not work on wayland
window.set_icon(Icon::try_from(test.as_slice()).unwrap());
}

while window.is_open() && !window.is_key_down(Key::Escape) {
Expand Down
74 changes: 42 additions & 32 deletions examples/image.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,53 @@
use minifb::{Key, ScaleMode, Window, WindowOptions};

Check warning on line 1 in examples/image.rs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

unused import: `ScaleMode`
use png::{Decoder, Transformations};
use std::fs::File;

fn main() {
use std::fs::File;
// The decoder is a build for reader and can be used to set various decoding options
// via `Transformations`. The default output transformation is `Transformations::EXPAND
// | Transformations::STRIP_ALPHA`.
let decoder = png::Decoder::new(File::open("resources/uv.png").unwrap());
let mut decoder = Decoder::new(File::open("examples/resources/planet.png").unwrap());

// Reading the image in RGBA format.
decoder.set_transformations(Transformations::ALPHA);
let mut reader = decoder.read_info().unwrap();
// Allocate the output buffer.
let mut buf = vec![0; reader.output_buffer_size()];
// Read the next frame. Currently this function should only called once.
// The default options
reader.next_frame(&mut buf).unwrap();
// convert buffer to u32

let u32_buffer: Vec<u32> = buf
.chunks(3)
.map(|v| ((v[0] as u32) << 16) | ((v[1] as u32) << 8) | v[2] as u32)
.collect();

let mut buffer = vec![0u32; reader.output_buffer_size()];

// View of pixels as individual subpixels (avoids allocating a second pixel buffer).
let mut u8_buffer = unsafe {
std::slice::from_raw_parts_mut(
buffer.as_mut_ptr() as *mut u8,
buffer.len() * std::mem::size_of::<u32>(),
)
};

// Read the next frame. Currently this function should only be called once.
reader.next_frame(&mut u8_buffer).unwrap();

// convert RGBA buffer read by the reader to an ARGB buffer as expected by minifb.
for (rgba, argb) in u8_buffer.chunks_mut(4).zip(buffer.iter_mut()) {
// extracting the subpixels
let r = rgba[0] as u32;
let g = rgba[1] as u32;
let b = rgba[2] as u32;
let a = rgba[3] as u32;

// merging the subpixels in ARGB format.
*argb = a << 24 | r << 16 | g << 8 | b;
}

let width = reader.info().width as usize;
let height = reader.info().height as usize;

let mut window = Window::new(
"Noise Test - Press ESC to exit",
reader.info().width as usize,
reader.info().height as usize,
WindowOptions {
resize: true,
scale_mode: ScaleMode::Center,
..WindowOptions::default()
},
"Image background example - Press ESC to exit",
width,
height,
WindowOptions::default(),
)
.expect("Unable to open Window");
.expect("Unable to create the window");

window.set_target_fps(60);

while window.is_open() && !window.is_key_down(Key::Escape) {
window
.update_with_buffer(
&u32_buffer,
reader.info().width as usize,
reader.info().height as usize,
)
.unwrap();
window.update_with_buffer(&buffer, width, height).unwrap();
}
}
Loading

0 comments on commit b574d4c

Please sign in to comment.