Skip to content

Commit c0b53bc

Browse files
authoredAug 11, 2022
Update game-of-life example (#23)
1 parent 30dedf0 commit c0b53bc

File tree

6 files changed

+71
-62
lines changed

6 files changed

+71
-62
lines changed
 

Diff for: ‎game-of-life/asconfig.json

+12-15
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
{
2+
"options": {
3+
"runtime": "stub",
4+
"use": "Math=JSMath",
5+
"importMemory": true,
6+
"sourceMap": true,
7+
"measure": true
8+
},
29
"targets": {
3-
"options": {
4-
"runtime": "stub",
5-
"sourceMap": true,
6-
"measure": true
7-
},
810
"debug": {
9-
"outFile": "build/untouched.wasm",
10-
"textFile": "build/untouched.wat",
11-
"use": "Math=JSMath",
12-
"importMemory": true,
11+
"outFile": "build/debug.wasm",
12+
"textFile": "build/debug.wat",
1313
"debug": true
1414
},
1515
"release": {
16-
"outFile": "build/optimized.wasm",
17-
"textFile": "build/optimized.wat",
18-
"use": "Math=JSMath",
19-
"importMemory": true,
16+
"outFile": "build/release.wasm",
17+
"textFile": "build/release.wat",
2018
"optimizeLevel": 3,
21-
"converge": false,
2219
"shrinkLevel": 0,
23-
"noAssert": false
20+
"noAssert": true
2421
}
2522
}
2623
}

Diff for: ‎game-of-life/assembly/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,21 @@ import { BGR_ALIVE, BGR_DEAD, BIT_ROT } from "./config";
66
var width: i32, height: i32, offset: i32;
77

88
/** Gets an input pixel in the range [0, s]. */
9+
// @ts-ignore: decorator
910
@inline
1011
function get(x: u32, y: u32): u32 {
1112
return load<u32>((y * width + x) << 2);
1213
}
1314

1415
/** Sets an output pixel in the range [s, 2*s]. */
16+
// @ts-ignore: decorator
1517
@inline
1618
function set(x: u32, y: u32, v: u32): void {
1719
store<u32>((offset + y * width + x) << 2, v);
1820
}
1921

2022
/** Sets an output pixel in the range [s, 2*s] while fading it out. */
23+
// @ts-ignore: decorator
2124
@inline
2225
function rot(x: u32, y: u32, v: u32): void {
2326
var alpha = max<i32>((v >> 24) - BIT_ROT, 0);

Diff for: ‎game-of-life/build/.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
*
22
!.gitignore
3-
!optimized.wasm
3+
!release.wasm
Binary file not shown.

Diff for: ‎game-of-life/index.html

+52-43
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@ <h1>
3131
const BIT_ROT = 10;
3232

3333
// Set up the canvas with a 2D rendering context
34-
var cnv = document.getElementsByTagName("canvas")[0];
35-
var ctx = cnv.getContext("2d");
36-
var bcr = cnv.getBoundingClientRect();
34+
var canvas = document.getElementsByTagName("canvas")[0];
35+
var ctx = canvas.getContext("2d");
36+
var bcr = canvas.getBoundingClientRect();
3737

3838
// Compute the size of the universe (here: 2px per cell)
39-
var width = bcr.width >>> 1;
40-
var height = bcr.height >>> 1;
41-
var size = width * height;
42-
var byteSize = (size + size) << 2; // input & output (here: 4b per cell)
39+
var width = bcr.width >>> 1;
40+
var height = bcr.height >>> 1;
41+
var size = width * height;
42+
var byteSize = (2 * size) << 2; // input & output (here: 4b per cell)
4343

44-
cnv.width = width;
45-
cnv.height = height;
46-
cnv.style = `
44+
canvas.width = width;
45+
canvas.height = height;
46+
canvas.style = `
4747
image-rendering: optimizeSpeed;
4848
image-rendering: -moz-crisp-edges;
4949
image-rendering: -webkit-optimize-contrast;
@@ -56,21 +56,23 @@ <h1>
5656
ctx.imageSmoothingEnabled = false;
5757

5858
// Compute the size of and instantiate the module's memory
59-
var memory = new WebAssembly.Memory({ initial: ((byteSize + 0xffff) & ~0xffff) >>> 16 });
59+
var memory = new WebAssembly.Memory({
60+
initial: ((byteSize + 0xffff) & ~0xffff) >>> 16
61+
});
6062

6163
// Fetch and instantiate the module
62-
fetch("build/optimized.wasm")
64+
fetch("build/release.wasm")
6365
.then(response => response.arrayBuffer())
6466
.then(buffer => WebAssembly.instantiate(buffer, {
6567
env: {
6668
memory,
67-
abort: function() {},
69+
abort() {},
6870
"Math.random": Math.random
6971
},
7072
config: {
71-
BGR_ALIVE : rgb2bgr(RGB_ALIVE) | 1, // little endian, LSB must be set
72-
BGR_DEAD : rgb2bgr(RGB_DEAD) & ~1, // little endian, LSB must not be set
73-
BIT_ROT
73+
BIT_ROT,
74+
BGR_ALIVE: rgb2bgr(RGB_ALIVE) | 1, // little endian, LSB must be set
75+
BGR_DEAD: rgb2bgr(RGB_DEAD) & ~1, // little endian, LSB must not be set
7476
},
7577
}))
7678
.then(module => {
@@ -84,45 +86,52 @@ <h1>
8486
// Update about 30 times a second
8587
(function update() {
8688
setTimeout(update, 1000 / 30);
87-
mem.copyWithin(0, size, size + size); // copy output to input
88-
exports.step(); // perform the next step
89+
mem.copyWithin(0, size, 2 * size); // copy output to input
90+
exports.step(); // perform the next step
8991
})();
9092

9193
// Keep rendering the output at [size, 2*size]
9294
var imageData = ctx.createImageData(width, height);
9395
var argb = new Uint32Array(imageData.data.buffer);
96+
9497
(function render() {
9598
requestAnimationFrame(render);
96-
argb.set(mem.subarray(size, size + size)); // copy output to image buffer
97-
ctx.putImageData(imageData, 0, 0); // apply image buffer
99+
argb.set(mem.subarray(size, 2 * size)); // copy output to image buffer
100+
ctx.putImageData(imageData, 0, 0); // apply image buffer
98101
})();
99102

100103
// When clicked or dragged, fill the current row and column with random live cells
101-
var down = false;
102-
[ [cnv, "mousedown"],
103-
[cnv, "touchstart"]
104-
].forEach(eh => eh[0].addEventListener(eh[1], e => down = true));
105-
[ [document, "mouseup"],
106-
[document, "touchend"]
107-
].forEach(eh => eh[0].addEventListener(eh[1], e => down = false));
108-
[ [cnv, "mousemove"],
109-
[cnv, "touchmove"],
110-
[cnv, "mousedown"]
111-
].forEach(eh => eh[0].addEventListener(eh[1], e => {
112-
if (!down) return;
113-
var loc;
114-
if (e.touches) {
115-
if (e.touches.length > 1) return;
116-
loc = e.touches[0];
117-
} else {
118-
loc = e;
119-
}
120-
var bcr = cnv.getBoundingClientRect();
121-
exports.fill((loc.clientX - bcr.left) >>> 1, (loc.clientY - bcr.top) >>> 1, 0.5);
122-
}));
104+
let down = false;
105+
for (const ty of ["mousedown", "touchstart"]) {
106+
canvas.addEventListener(ty, e => down = true);
107+
}
108+
for (const ty of ["mouseup", "touchend"]) {
109+
document.addEventListener(ty, e => down = false);
110+
}
111+
for (const ty of ["mousemove", "touchmove", "mousedown"]) {
112+
canvas.addEventListener(ty, e => {
113+
if (!down) return;
114+
const touches = e.touches;
115+
let loc;
116+
if (touches) {
117+
if (touches.length > 1) return;
118+
loc = touches[0];
119+
} else {
120+
loc = e;
121+
}
122+
const rect = canvas.getBoundingClientRect();
123+
exports.fill(
124+
(loc.clientX - rect.left) >>> 1,
125+
(loc.clientY - rect.top) >>> 1,
126+
0.5
127+
);
128+
});
129+
}
123130

124131
// :-(
125-
if (navigator.userAgent.indexOf(" Edge/") >= 0) document.getElementById("edge").style.display = "block";
132+
if (navigator.userAgent.includes(" Edge/")) {
133+
document.getElementById("edge").style.display = "block";
134+
}
126135
}).catch(err => {
127136
alert("Failed to load WASM: " + err.message + " (ad blocker, maybe?)");
128137
console.log(err.stack);

Diff for: ‎game-of-life/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
"license": "Apache-2.0",
55
"private": true,
66
"scripts": {
7-
"asbuild:untouched": "asc assembly/index.ts --target debug",
8-
"asbuild:optimized": "asc assembly/index.ts --target release",
9-
"asbuild": "npm run asbuild:untouched && npm run asbuild:optimized",
7+
"asbuild:debug": "asc assembly/index.ts --target debug",
8+
"asbuild:release": "asc assembly/index.ts --target release",
9+
"asbuild": "npm run asbuild:debug && npm run asbuild:release",
1010
"start": "npx serve"
1111
},
1212
"devDependencies": {

0 commit comments

Comments
 (0)