Skip to content

Instantly share code, notes, and snippets.

@bjfish
Created April 25, 2018 17:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bjfish/ff045fd6455ffa16af1030a0cde24cc5 to your computer and use it in GitHub Desktop.
Save bjfish/ff045fd6455ffa16af1030a0cde24cc5 to your computer and use it in GitHub Desktop.
GoL ASC Memory Visualzation index.html
<!DOCTYPE html>
<html>
<head>
<title>Conway's Game of Life - AssemblyScript</title>
<link rel="icon" href="http://assemblyscript.org/favicon.ico" type="image/x-icon" />
<meta name="viewport" content="user-scalable=0" />
<style>
/* html, body { height: 100%; margin: 0; overflow: hidden; color: #111; background: #fff; font-family: sans-serif; } */
/* body { border-top: 2px solid #bc18d4; }
h1 { padding: 18px 20px 20px; font-size: 12pt; margin: 0; }
a { color: #111; text-decoration: none; }
a:hover { color: #bc18d4; text-decoration: underline; }
canvas { position: absolute; top: 60px; left: 20px; width: calc(100% - 40px); height: calc(100% - 80px); background: #100707; cursor: cell; user-select: none; }
#edge { position: absolute; bottom: 40px; right: 40px; color: #fff; display: none; text-shadow: 0 1px 2px #000; -ms-user-select: none; user-select: none; } */
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/two.js/0.6.0/two.js"></script>
</head>
<body>
<h1>
<a href="https://en.wikipedia.org/wiki/Conway's_Game_of_Life">Conway's Game of Life</a> in
<a href="http://assemblyscript.org">AssemblyScript</a>
( <a href="https://github.com/AssemblyScript/assemblyscript/blob/master/examples/game-of-life/assembly/index.ts">source</a> )
</h1>
<div><canvas></canvas></div>
<div id="main"></div>
<div id="edge">Might be blurry because MS Edge does not support 'image-rendering: crisp-edges' (yet) :-(</div>
<script>"use strict";
// Configuration
const RGB_ALIVE = 0xD392E6;
const RGB_DEAD = 0xA61B85;
const BIT_ROT = 10;
// Set up the canvas with a 2D rendering context
var cnv = document.getElementsByTagName("canvas")[0];
var ctx = cnv.getContext("2d");
var bcr = cnv.getBoundingClientRect();
// Compute the size of the universe (here: 2px per cell)
var width = bcr.width >>> 1;
var height = bcr.height >>> 1;
var size = width * height;
var byteSize = (size + size) << 2; // input & output (here: 4b per cell)
cnv.width = width;
cnv.height = height;
cnv.style = `
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: -o-crisp-edges;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
`;
ctx.imageSmoothingEnabled = false;
// Compute the size of and instantiate the module's memory
var memory = new WebAssembly.Memory({ initial: ((byteSize + 0xffff) & ~0xffff) >>> 16 });
// Fetch and instantiate the module
fetch("build/optimized.wasm")
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.instantiate(buffer, {
env: {
RGB_ALIVE : rgb2le(RGB_ALIVE) | 1, // little endian, LSB must be set
RGB_DEAD : rgb2le(RGB_DEAD) & ~1, // little endian, LSB must not be set
BIT_ROT,
memory,
abort: function() {}
},
JSMath: Math
}))
.then(module => {
var exports = module.instance.exports;
// Initialize the module with the universe's width and height
exports.init(width, height);
var mem = new Uint32Array(memory.buffer);
// Update about 30 times a second
(function update() {
setTimeout(update, 1000 / 30);
mem.copyWithin(0, size, size + size); // copy output to input
exports.step(); // perform the next step
})();
function updateMem() {
console.log("ABou to updateMem");
var two = new Two({ height: 10000, width: 1200
}).appendTo(document.getElementById("main"));
var padHeight = 100;
var padWidth = 100;
var columns = 128;
var width = 8;
var height = 8;
var array = new Uint8Array(mem.buffer);
console.log("ABou to fill:" + array.length);
for (var i = 0; i < 10000; i++) {
var rect = two.makeRectangle(((i % columns) * height) + padWidth, (Math.floor(i / columns) * height) + padHeight, width ,height);
rect.fill = array[i] > 0 ? 'green': 'gray';
rect.stroke = 'orangered';
}
console.log("ABou to two.update");
two.update();
}
setTimeout(updateMem, 3000);
// Keep rendering the output at [size, 2*size]
var imageData = ctx.createImageData(width, height);
var argb = new Uint32Array(imageData.data.buffer);
(function render() {
requestAnimationFrame(render);
argb.set(mem.subarray(size, size + size)); // copy output to image buffer
ctx.putImageData(imageData, 0, 0); // apply image buffer
})();
// When clicked or dragged, fill the current row and column with random live cells
var down = false;
[ [cnv, "mousedown"],
[cnv, "touchstart"]
].forEach(eh => eh[0].addEventListener(eh[1], e => down = true));
[ [document, "mouseup"],
[document, "touchend"]
].forEach(eh => eh[0].addEventListener(eh[1], e => down = false));
[ [cnv, "mousemove"],
[cnv, "touchmove"],
[cnv, "mousedown"]
].forEach(eh => eh[0].addEventListener(eh[1], e => {
if (!down) return;
var loc;
if (e.touches) {
if (e.touches.length > 1) return;
loc = e.touches[0];
} else {
loc = e;
}
var bcr = cnv.getBoundingClientRect();
exports.fill((loc.clientX - bcr.left) >>> 1, (loc.clientY - bcr.top) >>> 1, 0.5);
}));
// :-(
if (navigator.userAgent.indexOf(" Edge/") >= 0) document.getElementById("edge").style.display = "block";
}).catch(err => {
alert("Failed to load WASM: " + err.message + " (ad blocker, maybe?)");
console.log(err.stack);
});
function rgb2le(rgb) {
return ((rgb >>> 16) & 0xff) | (rgb & 0xff00) | (rgb & 0xff) << 16;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment