From cac13d027e42e5c2dd2ec6466503f2c70fcfb434 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Fri, 10 Jan 2020 13:16:16 +0100 Subject: [PATCH] first throw for game of life... --- tutorial/wasm-game-of-life/src/lib.rs | 103 +++++++++++++++++++++- tutorial/wasm-game-of-life/www/index.html | 17 +++- tutorial/wasm-game-of-life/www/index.js | 14 ++- 3 files changed, 126 insertions(+), 8 deletions(-) diff --git a/tutorial/wasm-game-of-life/src/lib.rs b/tutorial/wasm-game-of-life/src/lib.rs index 9ee5376..2fe1e8c 100644 --- a/tutorial/wasm-game-of-life/src/lib.rs +++ b/tutorial/wasm-game-of-life/src/lib.rs @@ -1,5 +1,6 @@ mod utils; +use std::fmt::{Display, Formatter, Result}; use wasm_bindgen::prelude::*; // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global @@ -9,11 +10,105 @@ use wasm_bindgen::prelude::*; static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[wasm_bindgen] -extern { - fn alert(s: &str); +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Cell { + Dead = 0, + Alive = 1, } #[wasm_bindgen] -pub fn greet(s :&str) { - alert(&format!("Hello, {}!", s)); +pub struct Universe { + width :u32, + height :u32, + cells :Vec, +} + +#[wasm_bindgen] +impl Universe { + pub fn new() -> Universe { + let width = 64; + let height = 64; + + let init_cells = |i :u32| { + if i % 2 == 0 || i % 7 == 0 { Cell::Alive } else { Cell::Dead } + }; + + let cells = (0..width * height).map(init_cells).collect(); + + Universe { + width: width, + height: height, + cells: cells, + } + } + + pub fn render(&self) -> String { + self.to_string() + } + + pub fn tick(&mut self) { + let mut next = self.cells.clone(); + + for row in 0..self.height { + for col in 0..self.width { + let idx = self.get_index(row, col); + let cell = self.cells[idx]; + let live_neighbors = self.live_neighbor_count(row, col); + + // Game of life rules.... + let next_cell = match (cell, live_neighbors) { + (Cell::Alive, 2) | + (Cell::Alive, 3) => Cell::Alive, + (Cell::Alive, _) => Cell::Dead, + ( Cell::Dead, 3) => Cell::Alive, + ( otherwise, _) => otherwise, + }; + + next[idx] = next_cell; + } + } + + self.cells = next; + } + + fn get_index(&self, row :u32, col :u32) -> usize { + (row * self.width + col) as usize + } + + fn live_neighbor_count(&self, row :u32, col :u32) -> u8 { + let mut count = 0; + + for delta_row in [self.height - 1, 0, 1].iter().cloned() { + for delta_col in [self.width - 1, 0, 1].iter().cloned() { + if delta_row == 0 && delta_col == 0 { + continue; + } + + let neighbor_row = (row + delta_row) % self.height; + let neighbor_col = (col + delta_col) % self.width; + let idx = self.get_index(neighbor_row, neighbor_col); + count += self.cells[idx] as u8; + } + } + + count + } +} + +impl Display for Universe { + fn fmt(&self, f :&mut Formatter) -> Result { + for line in self.cells.as_slice().chunks(self.width as usize) { + for &cell in line { + let symbol = match cell { + Cell::Dead => ' ', + Cell::Alive => '*', + }; + write!(f, "{}", symbol)?; + } + write!(f, "\n")?; + } + + Ok(()) + } } diff --git a/tutorial/wasm-game-of-life/www/index.html b/tutorial/wasm-game-of-life/www/index.html index ca5615c..0d09239 100644 --- a/tutorial/wasm-game-of-life/www/index.html +++ b/tutorial/wasm-game-of-life/www/index.html @@ -2,10 +2,23 @@ - Hello wasm-pack! + wasm-game-of-life! + - +

     
   
 
diff --git a/tutorial/wasm-game-of-life/www/index.js b/tutorial/wasm-game-of-life/www/index.js
index b52012e..fb1bcde 100644
--- a/tutorial/wasm-game-of-life/www/index.js
+++ b/tutorial/wasm-game-of-life/www/index.js
@@ -1,3 +1,13 @@
-import * as wasm from "wasm-game-of-life";
+import { Universe } from "wasm-game-of-life";
 
-wasm.greet("It's all a game");
+const      pre = document.getElementById("game-of-life-canvas");
+const universe = Universe.new();
+
+const renderLoop = () => {
+    pre.textContent = universe.render();
+    universe.tick();
+
+    requestAnimationFrame(renderLoop);
+};
+
+requestAnimationFrame(renderLoop);