|
31 | 31 | const BIT_ROT = 10;
|
32 | 32 |
|
33 | 33 | // 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(); |
37 | 37 |
|
38 | 38 | // 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) |
43 | 43 |
|
44 |
| -cnv.width = width; |
45 |
| -cnv.height = height; |
46 |
| -cnv.style = ` |
| 44 | +canvas.width = width; |
| 45 | +canvas.height = height; |
| 46 | +canvas.style = ` |
47 | 47 | image-rendering: optimizeSpeed;
|
48 | 48 | image-rendering: -moz-crisp-edges;
|
49 | 49 | image-rendering: -webkit-optimize-contrast;
|
|
56 | 56 | ctx.imageSmoothingEnabled = false;
|
57 | 57 |
|
58 | 58 | // 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 | +}); |
60 | 62 |
|
61 | 63 | // Fetch and instantiate the module
|
62 |
| -fetch("build/optimized.wasm") |
| 64 | +fetch("build/release.wasm") |
63 | 65 | .then(response => response.arrayBuffer())
|
64 | 66 | .then(buffer => WebAssembly.instantiate(buffer, {
|
65 | 67 | env: {
|
66 | 68 | memory,
|
67 |
| - abort: function() {}, |
| 69 | + abort() {}, |
68 | 70 | "Math.random": Math.random
|
69 | 71 | },
|
70 | 72 | 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 |
74 | 76 | },
|
75 | 77 | }))
|
76 | 78 | .then(module => {
|
|
84 | 86 | // Update about 30 times a second
|
85 | 87 | (function update() {
|
86 | 88 | 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 |
89 | 91 | })();
|
90 | 92 |
|
91 | 93 | // Keep rendering the output at [size, 2*size]
|
92 | 94 | var imageData = ctx.createImageData(width, height);
|
93 | 95 | var argb = new Uint32Array(imageData.data.buffer);
|
| 96 | + |
94 | 97 | (function render() {
|
95 | 98 | 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 |
98 | 101 | })();
|
99 | 102 |
|
100 | 103 | // 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 | + } |
123 | 130 |
|
124 | 131 | // :-(
|
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 | + } |
126 | 135 | }).catch(err => {
|
127 | 136 | alert("Failed to load WASM: " + err.message + " (ad blocker, maybe?)");
|
128 | 137 | console.log(err.stack);
|
|
0 commit comments