Comments (2)
I was also stuck at this same point for a while. Including code that finally worked as a workaround for now:
src/lib.rs:
mod utils;
use std::fmt;
use wasm_bindgen::prelude::*;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Cell {
Dead = 0,
Alive = 1,
}
#[wasm_bindgen]
pub struct Universe {
width: u32,
height: u32,
cells: Vec<Cell>,
}
impl fmt::Display for Universe {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for line in self.cells.as_slice().chunks(self.width as usize) {
for &cell in line {
let symbol = if cell == Cell::Dead { '◻' } else { '◼' };
write!(f, "{}", symbol)?;
}
write!(f, "\n")?;
}
Ok(())
}
}
impl Universe {
fn get_index(&self, row: u32, column: u32) -> usize {
(row * self.width + column) as usize
}
fn live_neighbor_count(&self, row: u32, column: 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 = (column + delta_col) % self.width;
let idx = self.get_index(neighbor_row, neighbor_col);
count += self.cells[idx] as u8;
}
}
count
}
}
/// Public methods, exported to JavaScript.
#[wasm_bindgen]
impl Universe {
pub fn new() -> Universe {
let width = 64;
let height = 64;
let cells = (0..width * height)
.map(|i| {
if i % 2 == 0 || i % 7 == 0 {
Cell::Alive
} else {
Cell::Dead
}
})
.collect();
Universe {
width,
height,
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);
let next_cell = match (cell, live_neighbors) {
// Rule 1: Any live cell with fewer than two live neighbours
// dies, as if caused by underpopulation.
(Cell::Alive, x) if x < 2 => Cell::Dead,
// Rule 2: Any live cell with two or three live neighbours
// lives on to the next generation.
(Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive,
// Rule 3: Any live cell with more than three live
// neighbours dies, as if by overpopulation.
(Cell::Alive, x) if x > 3 => Cell::Dead,
// Rule 4: Any dead cell with exactly three live neighbours
// becomes a live cell, as if by reproduction.
(Cell::Dead, 3) => Cell::Alive,
// All other cells remain in the same state.
(otherwise, _) => otherwise,
};
next[idx] = next_cell;
}
}
self.cells = next;
}
// ...
}
www/index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello wasm-pack!</title>
<style>
body {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<pre id="game-of-life-canvas"></pre>
<script src="./bootstrap.js"></script>
</body>
</html>
www/index.js:
import { Universe } from "wasm-game-of-life";
const pre = document.getElementById("game-of-life-canvas");
const universe = Universe.new();
const renderLoop = () => {
pre.textContent = universe.render();
universe.tick();
requestAnimationFrame(renderLoop);
};
requestAnimationFrame(renderLoop);
from book.
You probably made the same mistake I did and missed the code under
To start the rendering process, we'll use the same code as above to start the first iteration of the rendering loop:
I came up with this because I didn't like the code duplication and, since async-await exists, I replaced the recursion with looping to make it clearer, then I realized that the Universe.tick()
is tied to the refresh rate (mine is 300Hz...), so I tried setTimeout, but the spinners looked a little glitchy, so I went back to requestAnimationFrame with extra code to skip if the frame time is too early:
(async function renderLoop() {
let lastTime;
while (true) {
// await new Promise((res) => setTimeout(res, 1000 / 60));
let time = await new Promise(requestAnimationFrame);
if (lastTime && time - lastTime < 1000 / 59) {
continue;
}
lastTime = time;
drawCells();
universe.tick();
}
})();
from book.
Related Issues (20)
- create-wasm-app won't run on node 18 on windows HOT 4
- Chat link in to discord channel requires "The Rust Programming Language" Server
- Stop recommending wee_alloc HOT 2
- Changes to code have no effect after first compilation HOT 5
- Canvas example needs HTML Canvas element
- Suggest using iterators instead of indexing
- [4.2] greet keeps saying "Hello, wasm-game-of-life!" HOT 1
- [4.2] Serving Locally fails HOT 3
- `wasm-pack build` generates two additional files
- Tutorial has vulnerability warnings and, after fixing those, fails at `npm run start`. HOT 3
- Can't show Game-of-Life HOT 2
- Cant run command npm run start from the www folder(following the book) HOT 4
- What is the status of this book and associated code? HOT 1
- Managed to run helloworld tuto once,with manual tweaking, then it stops working uncomprehensibly HOT 3
- Testing Life: `Unable to start the server: Operation not permitted`
- Is this repo looking for new contributors/maintainers? HOT 5
- FOR ANYONE WHO IS GOING THROUGH THE STEPS IN 'Hello, World' AND HAS ERRORS HOT 4
- I want to translate this user manual into Chinese so that there's a Chinese version of the book. What steps should I take to accomplish this?
- Problems at 'Hello World' step npm issues, willing to work through! HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from book.