Skip to content

Instantly share code, notes, and snippets.

@brunoro
Created September 4, 2016 08:54
Show Gist options
  • Save brunoro/d8bb8140b55284e321efa019905766f9 to your computer and use it in GitHub Desktop.
Save brunoro/d8bb8140b55284e321efa019905766f9 to your computer and use it in GitHub Desktop.
canvas demons of cyclic space
var initial_hue = 0.5;
var final_hue = 0.8;
var num_colors = 12;
var scale = 3;
function random_state(width, height) {
var state = [];
for (var h = 0; h < height; h++) {
line = [];
for (var w = 0; w < width; w++)
line.push(Math.floor(Math.random() * num_colors));
state.push(line);
}
return state;
}
function hsl2rgb(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [r * 255, g * 255, b * 255, 255];
}
function mod(a, b) {
var r = a % b;
return r >= 0 ? r : b + r;
}
function step(state) {
var next = [];
for (var i = 0; i < state.length; i++) {
var next_line = [];
for (var j = 0; j < state[i].length; j++) {
var center = state[i][j];
var up = state[mod(i - 1, state.length)][j];
var down = state[mod(i + 1, state.length)][j];
var left = state[i][mod(j - 1, state[i].length)];
var right = state[i][mod(j + 1, state[i].length)];
var next_center = center;
neighbors = [down, up, left, right];
for (var n = 0; n < neighbors.length; n++) {
if (neighbors[n] == mod(center + 1, num_colors)) {
next_center = neighbors[n];
}
}
next_line.push(next_center);
}
next.push(next_line);
}
return next;
}
function set_pixel(bitmap, x, y, color) {
var b = (x + y * bitmap.width) * 4;
bitmap.data[b] = color[0];
bitmap.data[b+1] = color[1];
bitmap.data[b+2] = color[2];
bitmap.data[b+3] = color[3];
}
function draw_rect(bitmap, x, y, s, color) {
var x_end = x + s;
var y_end = y + s;
for (var i = x; i < x_end; i++)
for (var j = y; j < y_end; j++)
set_pixel(bitmap, i, j, color);
}
function draw(state, ctx) {
var bitmap = ctx.createImageData(ctx.canvas.width, ctx.canvas.height);
var hue_step = (final_hue - initial_hue) / num_colors;
for (var i = 0; i < state.length; i++) {
for (var j = 0; j < state[i].length; j++) {
var hue = initial_hue + state[i][j] * hue_step;
var color = hsl2rgb(hue, 0.6, 0.4);
if (scale == 1)
set_pixel(bitmap, i, j, color);
else
draw_rect(bitmap, i * scale, j * scale, scale, color);
}
}
ctx.putImageData(bitmap, 0, 0);
}
var c = document.getElementById("demons");
var ctx = c.getContext("2d");
var state = random_state(c.width / scale, c.height / scale);
var latency = 100;
function trigger_draw() {
var start = new Date().getTime();
draw(state, ctx);
state = step(state);
var duration = new Date().getTime() - start;
if (duration > latency)
trigger_draw();
else
setTimeout(trigger_draw, latency - duration);
}
trigger_draw();
/*
c.onmousemove = function(e) {
var rel_x = e.clientX / window.innerWidth;
var rel_y = e.clientY / window.innerHeight;
final_hue = rel_x;
initial_hue = rel_y;
}
*/
<html>
<head>
<title>demons.js</title>
<style>
body {
margin: 0;
}
#container {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
canvas {
position: absolute;
width: 100%;
border: 0;
z-index: 0;
}
</style>
</head>
<body>
<div id="container">
<canvas id="demons" width="600px" height="600px">
</canvas>
</div>
</body>
<script src="demons.js"></script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment