[ Launch: Game of Life ] eb6dce8a38241912f9b2 by glena
-
-
Save glena/eb6dce8a38241912f9b2 to your computer and use it in GitHub Desktop.
Game of Life
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"description":"Game of Life","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"pingpong","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"ajax-caching":true,"thumbnail":"http://i.imgur.com/gB69Prj.png"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var svg = d3.select("svg"); | |
var rows = 60; | |
var cols = 90; | |
var marginBottom = 152; | |
var totalWidth = tributary.sw; | |
var totalHeight = tributary.sh - marginBottom; | |
var width = parseInt(totalWidth / cols); | |
var height = parseInt(totalHeight / rows); | |
function GameOflife(options) { | |
this.rows = options.rows; | |
this.cols = options.cols; | |
} | |
GameOflife.prototype.setInitialState = function(init) { | |
this.data = []; | |
for(var i = 0; i < this.rows; i++) { | |
for(var j = 0; j < this.cols; j++) { | |
this.data.push({ x: j, y: i, live: 0 }); | |
} | |
} | |
for(i = 0; i < init.length; i++) { | |
var pos = this.getPos(init[i][0], init[i][1]); | |
this.data[pos].live = 1; | |
} | |
}; | |
GameOflife.prototype.getPos = function(x, y) { | |
if ( x >= 0 && x < this.cols && y >= 0 && y < this.rows ) { | |
return (y * this.cols) + x; | |
} | |
return -1; | |
}; | |
GameOflife.prototype.getCell = function(x, y) { | |
var pos = this.getPos(x, y); | |
if (pos >= 0 && pos < this.data.length ) { | |
return this.data[pos]; | |
} | |
return {}; | |
}; | |
GameOflife.prototype.getNeighbours = function(cell) { | |
var x = cell.x; | |
var y = cell.y; | |
var cells = []; | |
cells.push(this.getCell(x - 1, y - 1)); | |
cells.push(this.getCell(x - 1, y)); | |
cells.push(this.getCell(x - 1, y + 1)); | |
cells.push(this.getCell(x, y - 1)); | |
cells.push(this.getCell(x, y + 1)); | |
cells.push(this.getCell(x + 1, y - 1)); | |
cells.push(this.getCell(x + 1, y)); | |
cells.push(this.getCell(x + 1, y + 1)); | |
return cells; | |
}; | |
GameOflife.prototype.nextGeneration = function() { | |
var newData = []; | |
for(var i = 0; i < this.data.length; i++) { | |
var cell = this.data[i]; | |
var live = 0; | |
var livesCount = 0; | |
var neighbours = this.getNeighbours(cell); | |
for (var j = 0; j < neighbours.length; j++) { | |
if (neighbours[j].live && neighbours[j].live == 1) { | |
livesCount = livesCount + 1; | |
} | |
} | |
//Rule 1; Any live cell with fewer than two live neighbours dies, as if | |
//caused by under-population. | |
if (livesCount < 2 && cell.live == 1) { | |
//console.log('dies'); | |
live = 0; | |
} | |
//Rule 2: Any live cell with two or three live neighbours lives on to the | |
//next generation. | |
if ((livesCount == 2 || livesCount == 3) && cell.live == 1) { | |
//console.log('keep living'); | |
live = 1; | |
} | |
//Rule 3; Any live cell with more than three live neighbours dies, | |
//as if by overcrowding. | |
if ((livesCount > 3) && cell.live == 1) { | |
//console.log('dies'); | |
live = 0; | |
} | |
//Rule 4: Any dead cell with exactly three live neighbours becomes a live cell, | |
//as if by reproduction. | |
if (livesCount == 3 && cell.live === 0) { | |
//console.log('born!'); | |
live = 1; | |
} | |
newData.push({x: cell.x, y: cell.y, live: live}); | |
} | |
this.data = newData; | |
} | |
GameOflife.prototype.draw = function() { | |
d3.selectAll("rect") | |
.data(this.data) | |
.attr('class', function(d) { return "live" + d.live; }); | |
} | |
GameOflife.prototype.start = function() { | |
this.nextGeneration(); | |
this.draw(); | |
} | |
svg.attr("width", totalWidth). | |
attr("height", totalHeight + marginBottom); | |
var gameOfLife = new GameOflife({ rows: rows, cols: cols}); | |
var graph = svg.append("g"). | |
attr("width", totalWidth). | |
attr("height", totalHeight); | |
var x = d3.scale.linear().domain([0, cols]).range([0, totalWidth]); | |
var y = d3.scale.linear().domain([0, rows]).range([0, totalHeight]); | |
function addButton(x, y, text, callback) { | |
var button = svg.append('g') | |
.classed('btn', true) | |
.attr('transform', 'translate('+[x,y]+')'); | |
button.append('rect') | |
.attr("width", 100) | |
.attr("height", 50) | |
.attr("x", 0) | |
.attr("y", 0); | |
button.append('text') | |
.attr("x", 20) | |
.attr("y", 30) | |
.text(text) | |
.on('click', callback); | |
} | |
var initialized = false; | |
function init() { | |
var state = []; | |
var maxInitailcells = parseInt(Math.random()*(rows*cols)); | |
for (var a = 0; a < maxInitailcells; a++) { | |
var item = [ | |
parseInt(Math.random()*cols), | |
parseInt(Math.random()*rows) | |
]; | |
state.push(item); | |
} | |
gameOfLife.setInitialState(state); | |
if (!initialized) { | |
var data = graph.selectAll("g.cell") | |
.data(gameOfLife.data); | |
data.enter().append("rect") | |
.classed('cell',true) | |
.attr("width", width - 0.3) | |
.attr("height", height - 0.3) | |
.attr("x", function(d) { return x(d.x); }) | |
.attr("y", function(d) { return y(d.y); }); | |
} | |
gameOfLife.draw(); | |
initialized = true; | |
} | |
var interval = null; | |
addButton(10, totalHeight + 20, 'Start >>', function(){ | |
interval = setInterval(function(){ gameOfLife.start(); }, 500); | |
}); | |
addButton(123, totalHeight + 20, 'RESET', function(){ | |
clearInterval(interval); | |
init(); | |
}); | |
addButton(250, totalHeight + 20, 'Stop', function(){ | |
clearInterval(interval); | |
}); | |
init(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rect { | |
background: #e1e1e1 !important; | |
} | |
.live0 { | |
fill: #e1e1e1; | |
} | |
.live1 { | |
fill: steelblue; | |
} | |
.btn rect { | |
border:1px solid black; | |
fill:#FFFFFF; | |
cursor:pointer; | |
} | |
.btn text { | |
cursor:pointer; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment