Commit cac13d027e42e5c2dd2ec6466503f2c70fcfb434

Authored by Georg Hopp
1 parent 37b4ac30

first throw for game of life...

1 1 mod utils;
2 2
  3 +use std::fmt::{Display, Formatter, Result};
3 4 use wasm_bindgen::prelude::*;
4 5
5 6 // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
... ... @@ -9,11 +10,105 @@ use wasm_bindgen::prelude::*;
9 10 static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
10 11
11 12 #[wasm_bindgen]
12   -extern {
13   - fn alert(s: &str);
  13 +#[repr(u8)]
  14 +#[derive(Clone, Copy, Debug, PartialEq, Eq)]
  15 +pub enum Cell {
  16 + Dead = 0,
  17 + Alive = 1,
14 18 }
15 19
16 20 #[wasm_bindgen]
17   -pub fn greet(s :&str) {
18   - alert(&format!("Hello, {}!", s));
  21 +pub struct Universe {
  22 + width :u32,
  23 + height :u32,
  24 + cells :Vec<Cell>,
  25 +}
  26 +
  27 +#[wasm_bindgen]
  28 +impl Universe {
  29 + pub fn new() -> Universe {
  30 + let width = 64;
  31 + let height = 64;
  32 +
  33 + let init_cells = |i :u32| {
  34 + if i % 2 == 0 || i % 7 == 0 { Cell::Alive } else { Cell::Dead }
  35 + };
  36 +
  37 + let cells = (0..width * height).map(init_cells).collect();
  38 +
  39 + Universe {
  40 + width: width,
  41 + height: height,
  42 + cells: cells,
  43 + }
  44 + }
  45 +
  46 + pub fn render(&self) -> String {
  47 + self.to_string()
  48 + }
  49 +
  50 + pub fn tick(&mut self) {
  51 + let mut next = self.cells.clone();
  52 +
  53 + for row in 0..self.height {
  54 + for col in 0..self.width {
  55 + let idx = self.get_index(row, col);
  56 + let cell = self.cells[idx];
  57 + let live_neighbors = self.live_neighbor_count(row, col);
  58 +
  59 + // Game of life rules....
  60 + let next_cell = match (cell, live_neighbors) {
  61 + (Cell::Alive, 2) |
  62 + (Cell::Alive, 3) => Cell::Alive,
  63 + (Cell::Alive, _) => Cell::Dead,
  64 + ( Cell::Dead, 3) => Cell::Alive,
  65 + ( otherwise, _) => otherwise,
  66 + };
  67 +
  68 + next[idx] = next_cell;
  69 + }
  70 + }
  71 +
  72 + self.cells = next;
  73 + }
  74 +
  75 + fn get_index(&self, row :u32, col :u32) -> usize {
  76 + (row * self.width + col) as usize
  77 + }
  78 +
  79 + fn live_neighbor_count(&self, row :u32, col :u32) -> u8 {
  80 + let mut count = 0;
  81 +
  82 + for delta_row in [self.height - 1, 0, 1].iter().cloned() {
  83 + for delta_col in [self.width - 1, 0, 1].iter().cloned() {
  84 + if delta_row == 0 && delta_col == 0 {
  85 + continue;
  86 + }
  87 +
  88 + let neighbor_row = (row + delta_row) % self.height;
  89 + let neighbor_col = (col + delta_col) % self.width;
  90 + let idx = self.get_index(neighbor_row, neighbor_col);
  91 + count += self.cells[idx] as u8;
  92 + }
  93 + }
  94 +
  95 + count
  96 + }
  97 +}
  98 +
  99 +impl Display for Universe {
  100 + fn fmt(&self, f :&mut Formatter) -> Result {
  101 + for line in self.cells.as_slice().chunks(self.width as usize) {
  102 + for &cell in line {
  103 + let symbol = match cell {
  104 + Cell::Dead => ' ',
  105 + Cell::Alive => '*',
  106 + };
  107 + write!(f, "{}", symbol)?;
  108 + }
  109 + write!(f, "\n")?;
  110 + }
  111 +
  112 + Ok(())
  113 + }
19 114 }
... ...
... ... @@ -2,10 +2,23 @@
2 2 <html>
3 3 <head>
4 4 <meta charset="utf-8">
5   - <title>Hello wasm-pack!</title>
  5 + <title>wasm-game-of-life!</title>
  6 + <style>
  7 + body {
  8 + position: absolute;
  9 + top: 0;
  10 + left: 0;
  11 + width: 100%;
  12 + height: 100%;
  13 + display: flex;
  14 + flex-direction: column;
  15 + align-items: center;
  16 + justify-content: center;
  17 + }
  18 + </style>
6 19 </head>
7 20 <body>
8   - <noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
  21 + <pre id="game-of-life-canvas"></pre>
9 22 <script src="./bootstrap.js"></script>
10 23 </body>
11 24 </html>
... ...
1   -import * as wasm from "wasm-game-of-life";
  1 +import { Universe } from "wasm-game-of-life";
2 2
3   -wasm.greet("It's all a game");
  3 +const pre = document.getElementById("game-of-life-canvas");
  4 +const universe = Universe.new();
  5 +
  6 +const renderLoop = () => {
  7 + pre.textContent = universe.render();
  8 + universe.tick();
  9 +
  10 + requestAnimationFrame(renderLoop);
  11 +};
  12 +
  13 +requestAnimationFrame(renderLoop);
... ...
Please register or login to post a comment