Skip to content

Instantly share code, notes, and snippets.

@mohayonao
Created March 21, 2012 05:25
Show Gist options
  • Save mohayonao/2144751 to your computer and use it in GitHub Desktop.
Save mohayonao/2144751 to your computer and use it in GitHub Desktop.
LifeGame
var LifeGame = (function() {
var LifeGame = (function() {
var LifeGame = function() {
initialize.apply(this, arguments);
}, $this = LifeGame.prototype;
LifeGame.recentInstance = null;
var initialize = function(options) {
options = options || {};
this.cols = options.cols || 16;
this.rows = options.rows || 16;
this._currValues = new Uint8Array(this.cols * this.rows);
this._prevValues = new Uint8Array(this.cols * this.rows);
this._fix = !!options.fix;
LifeGame.recentInstance = this;
};
$this.curr = function() {
return this._currValues;
};
$this.prev = function() {
return this._prevValues;
};
$this.put = function(x, y, value) {
var i;
i = y * this.cols + x;
this._prevValues[i] = this._currValues[i];
if (this._fix) {
if (value !== undefined) {
this._currValues[i] = (value|0) % 3;
} else {
this._currValues[i] = (this._currValues[i] + 2) % 3;
}
} else {
if (value !== undefined) {
this._currValues[i] = value ? 1 : 0;
} else {
this._currValues[i] = 1 - this._currValues[i];
}
}
};
$this.count = function(x, y) {
var sum, values, cols, rows;
sum = 0;
values = this._currValues;
cols = this.cols;
rows = this.rows;
if (x > 0) {
if (y > 0) {
sum += values[(y-1) * cols + x-1] ? 1 : 0;
}
sum += values[y * cols + x-1] ? 1 : 0;
if (y < rows - 1) {
sum += values[(y+1) * cols + x-1] ? 1 : 0;
}
}
if (y > 0) {
sum += values[(y-1) * cols + x] ? 1 : 0;
}
if (y < rows - 1) {
sum += values[(y+1) * cols + x] ? 1 : 0;
}
if (x < cols - 1) {
if (y > 0) {
sum += values[(y-1) * cols + x+1] ? 1 : 0;
}
sum += values[y * cols + x+1] ? 1 : 0;
if (y < rows - 1) {
sum += values[(y+1) * cols + x+1] ? 1 : 0;
}
}
return sum;
};
$this.next = function() {
var prevValues, currValues, nextValues;
var cols, rows;
var i, x, y, c;
prevValues = this._prevValues;
currValues = this._currValues;
nextValues = new Uint8Array(currValues);
cols = this.cols;
rows = this.rows;
for (i = prevValues.length; i--; ) {
prevValues[i] = currValues[i];
}
i = 0;
for (y = 0; y < rows; y++) {
for (x = 0; x < cols; x++) {
if (currValues[i] !== 2) {
c = this.count(x, y);
if (currValues[i]) {
if (c <= 1 || 4 <= c) {
nextValues[i] = 0;
}
} else {
if (c === 3) {
nextValues[i] = 1;
}
}
}
i += 1;
}
}
for (i = currValues.length; i--; ) {
currValues[i] = nextValues[i];
}
};
return LifeGame;
}());
var LifeGameViewer = (function() {
var LifeGameViewer = function() {
initialize.apply(this, arguments);
}, $this = LifeGameViewer.prototype;
var initialize = function(sys, options) {
if (!(sys instanceof LifeGame)) {
options = sys;
sys = LifeGame.recentInstance;
}
options = options || {};
this.sys = sys;
this.width = options.width || (sys.cols * 10) || 640;
this.height = options.height || (sys.rows * 10) || 640;
this._cols = sys.cols;
this._rows = sys.rows;
initViewer.call(this, options.elem, options);
};
var initViewer = function(elem, options) {
var self = this;
if (elem instanceof HTMLCanvasElement) {
this._canvas = elem;
} else if (elem instanceof HTMLElement) {
this._canvas = document.createElement("canvas");
elem.appendChild(this._canvas);
} else {
this._canvas = null;
}
if (this._canvas !== null) {
this._canvas.style.position = "relative";
this._canvas.width = this._canvas.style.width = this.width;
this._canvas.height = this._canvas.style.height = this.height;
this._context = this._canvas.getContext("2d");
this._dx = this.width / this._cols;
this._dy = this.height / this._rows;
this._highlight = {x: -1, y: -1};
this._canvas.addEventListener("click", function(e) {
var x, y;
x = e.offsetX || e.layerX;
y = e.offsetY || e.layerY;
self.sys.put((x/self._dx)|0, (y/self._dy)|0);
}, false);
}
this.lv_color = options.lv_color || "blue";
this.fx_color = options.fx_color || "red";
this.hl_color = options.hl_color || "rgba(255, 255, 128, 0.75)";
this.bg_color = options.bg_color || "rgba(192, 192, 192, 0.25)";
};
var requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback, element){
window.setTimeout(callback, 1000 / 60);
};
$this.hl = function(value) {
var hl = {x:-1, y:-1};
value = value || {};
if (value.x !== undefined) hl.x = value.x;
if (value.y !== undefined) hl.y = value.y;
this._highlight = hl;
};
$this.animate = function() {
var self = this;
var context;
var values, dx, dy;
var cols, rows, w, h;
context = this._context;
values = this.sys.curr();
cols = this._cols;
rows = this._rows;
dx = this._dx;
dy = this._dy;
w = dx - 1;
if (w < 1) w = 1;
h = dy - 1;
if (h < 1) h = 1;
var _animate = function() {
var i, x, y;
var lv_color, fx_color, hl_color, bg_color;
var hlx, hly;
lv_color = self.lv_color;
fx_color = self.fx_color;
hl_color = self.hl_color;
bg_color = self.bg_color;
hlx = self._highlight.x;
hly = self._highlight.y;
i = 0;
for (y = 0; y < rows; y++) {
for (x = 0; x < cols; x++) {
if (values[i] === 1) {
context.fillStyle = lv_color;
} else if (values[i] === 2) {
context.fillStyle = fx_color;
} else {
if (hlx === x || hly === y) {
context.fillStyle = hl_color;
} else {
context.fillStyle = bg_color;
}
}
context.fillRect(x*dx, y*dy, w, h);
i++;
}
}
if (self._isAnimate) requestAnimationFrame(_animate);
};
this._isAnimate = true;
requestAnimationFrame(_animate);
};
return LifeGameViewer;
}());
LifeGame.Viewer = LifeGameViewer;
return LifeGame;
}());
jQuery(function() {
var elem = document.getElementById("canvas");
var game = new LifeGame({cols:32, rows:32});
var view = new LifeGame.Viewer({elem:elem, width:256, height:256});
view.animate();
jQuery("#bang").on("click", function() {
var i, curr;
curr = game.curr();
for (i = 0; i < curr.length; i++) {
if (curr[i] === 0) {
curr[i] = (Math.random() < 0.15) ? 1 : 0;
}
}
});
(function() {
var index = 0;
setInterval(function() {
if (index % 2 === 0) {
game.next();
}
view.hl({x:index % game.cols, y:index % game.rows});
index += 1;
}, 125);
}());
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment