summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs (renamed from src/main.rs)143
1 files changed, 109 insertions, 34 deletions
diff --git a/src/main.rs b/src/lib.rs
index a9af30d..cbac12e 100644
--- a/src/main.rs
+++ b/src/lib.rs
@@ -1,54 +1,114 @@
+use std::rc::Rc;
+
use pixels::wgpu::Color;
use pixels::PixelsBuilder;
use pixels::SurfaceTexture;
+use rand::distributions::Distribution;
use rand::distributions::Standard;
-use rand::prelude::Distribution;
-use winit::dpi::PhysicalSize;
+use wasm_bindgen::prelude::*;
+use winit::dpi::LogicalSize;
use winit::event::Event;
use winit::event_loop::EventLoop;
use winit::window::WindowBuilder;
use winit_input_helper::WinitInputHelper;
-const RES_X: usize = 265;
-const RES_Y: usize = 265;
+// const WIDTH: usize = 256;
+// const HEIGHT: usize = 256;
-const WIN_WIDTH: u32 = 4 * RES_X as u32;
-const WIN_HEIGHT: u32 = 4 * RES_Y as u32;
+#[wasm_bindgen(start)]
+async fn start() -> Result<(), JsValue> {
+ return run().await.map_err(|err| JsValue::from(err.to_string()));
+}
-fn main() -> anyhow::Result<()> {
+async fn run() -> anyhow::Result<()> {
let event_loop = EventLoop::new();
+
+ // let size = LogicalSize {
+ // width: WIDTH as f64,
+ // height: HEIGHT as f64,
+ // };
+
let window = WindowBuilder::new()
- .with_inner_size(PhysicalSize {
- width: WIN_WIDTH,
- height: WIN_HEIGHT,
- })
- .with_resizable(false)
+ // .with_inner_size(size)
+ // .with_min_inner_size(size)
.build(&event_loop)?;
+
+ let window = Rc::new(window);
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ use winit::platform::web::WindowExtWebSys;
+
+ // Retrieve current width and height dimensions of browser client window
+ let get_window_size = || {
+ let client_window = web_sys::window().unwrap();
+ LogicalSize::new(
+ client_window.inner_width().unwrap().as_f64().unwrap(),
+ client_window.inner_height().unwrap().as_f64().unwrap(),
+ )
+ };
+
+ let window = Rc::clone(&window);
+
+ // Initialize winit window with current dimensions of browser client
+ window.set_inner_size(get_window_size());
+
+ let client_window = web_sys::window().unwrap();
+
+ // Attach winit canvas to body element
+ web_sys::window()
+ .and_then(|win| win.document())
+ .and_then(|doc| doc.body())
+ .and_then(|body| {
+ body.append_child(&web_sys::Element::from(window.canvas()))
+ .ok()
+ })
+ .expect("couldn't append canvas to document body");
+
+ // Listen for resize event on browser client. Adjust winit window dimensions
+ // on event trigger
+ let closure = wasm_bindgen::closure::Closure::wrap(Box::new(move |_e: web_sys::Event| {
+ let size = get_window_size();
+ window.set_inner_size(size)
+ }) as Box<dyn FnMut(_)>);
+ client_window
+ .add_event_listener_with_callback("resize", closure.as_ref().unchecked_ref())
+ .unwrap();
+ closure.forget();
+ }
+
let mut input = WinitInputHelper::new();
let window_size = window.inner_size();
- let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
+ let surface_texture =
+ SurfaceTexture::new(window_size.width, window_size.height, window.as_ref());
+
+ let width = window_size.width / 8;
+ let height = window_size.height / 8;
- let mut pixels = PixelsBuilder::new(RES_X as u32, RES_Y as u32, surface_texture)
+ web_sys::console::log_1(&format!("{} x {}", width, height).into());
+
+ let mut pixels = PixelsBuilder::new(width, height, surface_texture)
.clear_color(Color {
r: 0.0,
g: 0.0,
b: 0.0,
a: 1.0,
})
- .build()?;
- let mut life = Life::new();
+ .build_async()
+ .await?;
+ let mut life = Life::new(width as usize, height as usize);
event_loop.run(move |event, _, control_flow| {
control_flow.set_poll();
if let Event::RedrawRequested(_) = event {
- life.draw(pixels.get_frame());
+ life.draw(pixels.frame_mut());
pixels.render().expect("failed to render");
}
if input.update(&event) {
- if input.quit() {
+ if input.close_requested() || input.destroyed() {
control_flow.set_exit();
return;
};
@@ -67,7 +127,9 @@ enum Cell {
#[derive(Debug)]
struct Grid {
- pub cells: [[Cell; RES_X]; RES_Y],
+ pub width: usize,
+ pub height: usize,
+ pub cells: Vec<Vec<Cell>>,
}
enum FrontGrid {
@@ -76,6 +138,8 @@ enum FrontGrid {
}
struct Life {
+ pub width: usize,
+ pub height: usize,
grid_a: Grid,
grid_b: Grid,
front_grid: FrontGrid,
@@ -91,26 +155,30 @@ impl Cell {
}
impl Grid {
- pub fn blank() -> Self {
+ pub fn blank(width: usize, height: usize) -> Self {
Self {
- cells: [[Cell::Dead { since: 0xff }; RES_X]; RES_Y],
+ width,
+ height,
+ cells: vec![vec![Cell::Dead { since: 0xff }; width]; height],
}
}
- pub fn with_random_borders() -> Self {
- let mut ret = Self::blank();
+ pub fn with_random_borders(width: usize, height: usize) -> Self {
+ let mut ret = Self::blank(width, height);
ret.randomize_border();
ret
}
pub fn randomize_border(&mut self) {
- self.cells[RES_X - 1] = rand::random();
+ for col in 0..self.width {
+ self.cells[self.height - 1][col] = rand::random();
+ }
}
pub fn draw(&self, frame: &mut [u8]) {
- for row in 0..RES_X {
- for col in 0..RES_Y {
- let pixel_idx = 4 * (RES_X * row + col);
+ for row in 0..self.height {
+ for col in 0..self.width {
+ let pixel_idx = 4 * (self.width * row + col);
match self.cells[row][col] {
Cell::Alive => {
@@ -138,8 +206,8 @@ impl Grid {
pub fn num_alive_neighbors(&self, row: usize, col: usize) -> u8 {
let mut ret = 0;
- for i in row.saturating_sub(1)..=(row + 1).min(RES_X - 1) {
- for j in col.saturating_sub(1)..=(col + 1).min(RES_Y - 1) {
+ for i in row.saturating_sub(1)..=(row + 1).min(self.height - 1) {
+ for j in col.saturating_sub(1)..=(col + 1).min(self.width - 1) {
if self.cells[i][j].is_alive() {
ret += 1;
}
@@ -175,10 +243,12 @@ impl Grid {
}
impl Life {
- pub fn new() -> Self {
+ pub fn new(width: usize, height: usize) -> Self {
Life {
- grid_a: Grid::with_random_borders(),
- grid_b: Grid::blank(),
+ width,
+ height,
+ grid_a: Grid::with_random_borders(width, height),
+ grid_b: Grid::blank(width, height),
front_grid: FrontGrid::A,
}
}
@@ -188,10 +258,11 @@ impl Life {
}
pub fn update(&mut self) {
+ let (width, height) = self.dimensions();
let (front, back) = self.grids();
- for row in 0..RES_X {
- for col in 0..RES_Y {
+ for row in 0..height {
+ for col in 0..width {
back.cells[row][col] = front.new_state(row, col);
}
}
@@ -200,6 +271,10 @@ impl Life {
self.swap_grids();
}
+ fn dimensions(&self) -> (usize, usize) {
+ (self.width, self.height)
+ }
+
fn grids(&mut self) -> (&Grid, &mut Grid) {
match self.front_grid {
FrontGrid::A => (&self.grid_a, &mut self.grid_b),