301 lines
11 KiB
HTML
Executable File
301 lines
11 KiB
HTML
Executable File
<html>
|
|
<head>
|
|
<style>
|
|
canvas {
|
|
image-rendering: optimizeSpeed; /* Older versions of FF */
|
|
image-rendering: -moz-crisp-edges; /* FF 6.0+ */
|
|
image-rendering: -webkit-optimize-contrast; /* Safari */
|
|
image-rendering: -o-crisp-edges; /* OS X & Windows Opera (12.02+) */
|
|
image-rendering: pixelated; /* Awesome future-browsers */
|
|
-ms-interpolation-mode: nearest-neighbor; /* IE */
|
|
|
|
}
|
|
|
|
html, body {
|
|
padding: 0px;
|
|
margin: 0px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<canvas id="canvas"></canvas>
|
|
</body>
|
|
<script type="text/javascript">
|
|
var grid = new Array();
|
|
var newGrid = new Array();
|
|
|
|
var scaleX = 10 ;
|
|
var scaleY = 10 ;
|
|
|
|
var width = Math.round( ( window.innerWidth/scaleX ) / 2 ) * 2 ;
|
|
var height = Math.round( ( window.innerHeight/scaleY ) / 2 ) * 2 ;
|
|
|
|
var element = document.getElementById('canvas');
|
|
|
|
var context = element.getContext('2d');
|
|
|
|
var step = 0.005 ;
|
|
|
|
var ratio = 1 ;
|
|
|
|
var ratioIndex = 0 ;
|
|
|
|
var hue = 0.6 ;
|
|
|
|
var speed = 1.0;
|
|
|
|
|
|
|
|
var HSV = function(h, s, v, a){
|
|
var self = this ;
|
|
self.h = h ;
|
|
self.s = s ;
|
|
self.v = v ;
|
|
self.a = a ;
|
|
|
|
self.toRGB = function() {
|
|
var r, g, b, i, f, p, q, t;
|
|
var h = self.h;
|
|
var s = self.s;
|
|
var v = self.v;
|
|
if (arguments.length === 1) {
|
|
s = h.s, v = h.v, h = h.h;
|
|
}
|
|
i = Math.floor(h * 6);
|
|
f = h * 6 - i;
|
|
p = v * (1 - s);
|
|
q = v * (1 - f * s);
|
|
t = v * (1 - (1 - f) * s);
|
|
switch (i % 6) {
|
|
case 0: r = v, g = t, b = p; break;
|
|
case 1: r = q, g = v, b = p; break;
|
|
case 2: r = p, g = v, b = t; break;
|
|
case 3: r = p, g = q, b = v; break;
|
|
case 4: r = t, g = p, b = v; break;
|
|
case 5: r = v, g = p, b = q; break;
|
|
}
|
|
return {
|
|
r: Math.round(r * 255),
|
|
g: Math.round(g * 255),
|
|
b: Math.round(b * 255)
|
|
};
|
|
}
|
|
|
|
}
|
|
|
|
function countNeighbours(xPos, yPos){
|
|
var n = 0;
|
|
for(var x=-1;x<2;x++){
|
|
for(var y=-1;y<2;y++){
|
|
var calcX = (xPos+x);
|
|
var calcY = (yPos+y);
|
|
|
|
if(calcX == width){
|
|
calcX = 0;
|
|
}
|
|
else if(calcX == -1){
|
|
calcX = width - 1;
|
|
}
|
|
|
|
if(calcY == height){
|
|
calcY = 0;
|
|
}
|
|
else if(calcY == -1){
|
|
calcY = height - 1;
|
|
}
|
|
|
|
var state = grid[calcX][calcY];
|
|
if((x != 0 || y != 0) && state == 1){
|
|
n++;
|
|
}
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
var imagedata = context.createImageData(width, height);
|
|
|
|
function placeGlider(){
|
|
placeSchematic( Math.floor(Math.random() * (width-4)) , Math.floor(Math.random() * (height-4)) , glider , Math.floor(Math.random()*4) );
|
|
setTimeout(placeGlider, 1000 * (1/speed));
|
|
}
|
|
|
|
function init(){
|
|
context.canvas.width = width ;
|
|
context.canvas.height = height ;
|
|
element.style.width = width * scaleX ;
|
|
element.style.height = height * scaleY ;
|
|
|
|
|
|
|
|
for(var x=0;x<width;x++){
|
|
grid[x] = new Array();
|
|
newGrid[x] = new Array();
|
|
for(var y=0;y<height;y++){
|
|
grid[x][y] = 0; // Math.floor(Math.random() * 2) + 0 : (Math.floor(Math.random() * 5) == 1) ;
|
|
newGrid[x][y] = 0;
|
|
}
|
|
}
|
|
|
|
placeGlider();
|
|
|
|
placeSchematic( Math.round(width/2)+4, Math.round(height/2) , glider , 2 );
|
|
placeSchematic( Math.round(width/2), Math.round(height/2)+4 , glider , 0 );
|
|
placeSchematic( Math.round(width/2), Math.round(height/2) , glider , 1 );
|
|
|
|
}
|
|
|
|
var glider = [ [0, 1, 0],
|
|
[1, 0, 0],
|
|
[1, 1, 1]];
|
|
|
|
function placeSchematic (xPos , yPos , s, r){
|
|
for(var n=0;n<r;n++){
|
|
s = mirrorArr(RotateMatrix(s , s.length ) );
|
|
}
|
|
|
|
for(var x=0;x<s.length;x++){
|
|
for(var y=0;y<s[0].length;y++){
|
|
grid[xPos+x][yPos+y] = s[y][x] ;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function mirrorArr(a) {
|
|
return a.map(function(arr){return arr.reverse();});
|
|
}
|
|
|
|
function RotateMatrix(a) {
|
|
return Object.keys(a[0]).map(
|
|
function (c) {
|
|
return a.map(function (r) {
|
|
return r[c];
|
|
|
|
});
|
|
}
|
|
);
|
|
}
|
|
|
|
|
|
function update(){
|
|
ratioIndex += speed ;
|
|
if(ratioIndex >= ratio){
|
|
|
|
ratioIndex = 0;
|
|
|
|
for(var x=0;x<width;x++){
|
|
for(var y=0;y<height;y++){
|
|
var n = countNeighbours(x, y);
|
|
if(grid[x][y] < 1){
|
|
if(n == 3){
|
|
newGrid[x][y] = 1;
|
|
}
|
|
else {
|
|
newGrid[x][y] = Math.max(grid[x][y] - step * speed , 0);
|
|
}
|
|
}
|
|
else if(grid[x][y] == 1) {
|
|
if(n < 2 || n > 3){
|
|
newGrid[x][y] = 1 - step ;
|
|
}
|
|
if(n == 2 || n == 3){
|
|
newGrid[x][y] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for(var x=0;x<width;x++){
|
|
for(var y=0;y<height;y++){
|
|
if(grid[x][y] < 1) {
|
|
newGrid[x][y] = Math.max(grid[x][y] - step * speed , 0);
|
|
}
|
|
else {
|
|
newGrid[x][y] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for(var x=0;x<width;x++){
|
|
for(var y=0;y<height;y++){
|
|
grid[x][y] = newGrid[x][y];
|
|
|
|
var pixelindex = (y * width + x) * 4;
|
|
|
|
// Generate a xor pattern with some random noise
|
|
var intensity = grid[x][y] ;
|
|
|
|
var color = new HSV( hue + (0.2*intensity) , intensity > (1-step) ? 0.1 : 0.25+intensity , intensity*intensity , 1 ).toRGB();
|
|
var red = color.r ;
|
|
var green = color.g ;
|
|
var blue = color.b ;
|
|
|
|
// var red = green = blue = intensity * 255 ;
|
|
|
|
// Set the pixel data
|
|
imagedata.data[pixelindex] = red; // Red
|
|
imagedata.data[pixelindex+1] = green; // Green
|
|
imagedata.data[pixelindex+2] = blue; // Blue
|
|
imagedata.data[pixelindex+3] = 255; // Alpha
|
|
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
init();
|
|
|
|
function point(x, y, canvas){
|
|
canvas.beginPath();
|
|
canvas.moveTo(x, y);
|
|
canvas.lineTo(x+1, y+1);
|
|
canvas.stroke();
|
|
}
|
|
|
|
function draw(){
|
|
window.requestAnimationFrame(draw);
|
|
|
|
update();
|
|
|
|
context.putImageData(imagedata, 0, 0);
|
|
|
|
}
|
|
|
|
draw();
|
|
|
|
var looping = false;
|
|
setInterval(function(){
|
|
if(looping){
|
|
hue = hue+0.01;
|
|
hue = hue>1?0:hue;
|
|
}
|
|
},400);
|
|
|
|
document.addEventListener ('keydown', function (event) {
|
|
if (event.which == 38) {
|
|
hue = Math.min(hue+0.01, 1);
|
|
}
|
|
else if(event.which == 40){
|
|
hue = Math.max(hue-0.01, 0);
|
|
}
|
|
|
|
if (event.which == 37) {
|
|
speed = Math.min(speed+0.01, 1);
|
|
}
|
|
else if(event.which == 39){
|
|
speed = Math.max(speed-0.01, 0.1 );
|
|
}
|
|
if (event.which == 32){
|
|
looping = looping?false:true;
|
|
}
|
|
|
|
});
|
|
|
|
</script>
|
|
</html> |