Post all your tuts or request for tuts here.
Verahta
Posts: 440 Joined: Wed Aug 24, 2011 1:50 am
Post
by Verahta » Wed Aug 06, 2014 8:59 pm
Found this pretty neat Python tutorial for
Conway's Game of Life (cellular automata):
http://stanford.edu/~cpiech/cs221/hando ... orial.html
You create mathematical patterns that seem to take on a life of their own:
Game of Life Overview
Our "Game of Life" board will be an n-by-n grid of square cells, each of which can be either "alive" or "dead". A given cell's neighbors are those cells directly above, below, left, or right of the cell, plus with the cells diagonally adjacent to it (the cells touching its diagonals). Each cell changes from one time step to the next according to the following rules:
Any living cell with fewer than two living neighbors dies.
Any living cell with exactly two or exactly three living neighbors remains alive.
Any living cell with more than three living neighbors dies.
Any dead cell with exactly three living neighbors becomes alive.
These extremely simple rules give rise to some incredibly complex and beautiful patterns, as illustrated here:
In fact, these rules are so powerful that they actually allow Conway's Game of Life to be Turing Complete, which roughly means that we could perform any computation within the game that a standard computer could (though they would be painfully slow). And to just get super meta for a second, a consequence of this is that Game of Life can simulate ITSELF! (#Conwayception)
[YouTube]
https://www.youtube.com/watch?v=D6aP9S9rEQk [/YouTube]
"In order to understand recursion, one must first understand recursion".
Jackolantern
Posts: 10891 Joined: Wed Jul 01, 2009 11:00 pm
Post
by Jackolantern » Sun Aug 10, 2014 6:22 am
I have always had a strange fascination with Conway's Game of Life
The indelible lord of tl;dr
Verahta
Posts: 440 Joined: Wed Aug 24, 2011 1:50 am
Post
by Verahta » Mon Aug 18, 2014 7:51 pm
"In order to understand recursion, one must first understand recursion".
Chris
Posts: 1580 Joined: Wed Sep 30, 2009 7:22 pm
Post
by Chris » Mon Aug 18, 2014 11:54 pm
Cool! that inspired me to make this
See which color is most dominant
Code: Select all
<html>
<head>
<style type="text/css">
*{ padding: 0px; margin: 0px; background: #000; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
lifeFormSquareSize = 5;
var Point = function(x,y) {
this.x = x || parseInt(Math.random() * (window.innerWidth/lifeFormSquareSize));
this.y = y || parseInt(Math.random() * (window.innerHeight/lifeFormSquareSize));
return this;
}
Point.prototype.constructor = Point;
Point.prototype = {
x : 0,
y : 0,
colidesWith : function(point) {
return point.x == this.x && point.y == this.y;
},
moveRandomly : function() {
var randomX = Math.random() * 10;
var randomY = Math.random() * 10;
var displaceX = parseInt(Math.random()*lifeFormSquareSize);
var displaceY = parseInt(Math.random()*lifeFormSquareSize);
this.x = parseInt(randomX > 7.5 ? (this.x+displaceX) : (randomX > 5 ? (this.x-displaceX) : this.x));
this.y = parseInt(randomY > 7.5 ? (this.y+displaceY) : (randomY > 5 ? (this.y-displaceY) : this.y));
}
}
var lifeFormList = [];
var LifeForm = function() {
lifeFormList.push(this);
this.point = new Point();
this.color = '#' +(Math.random()*0xFFFFFF<<0).toString(16);
return this;
}
LifeForm.prototype.contructor = LifeForm;
LifeForm.prototype = {
color : '#000000',
point : null,
takeTurn : function() {
for(var i in lifeFormList) {
if(lifeFormList[i] !== this) {
if(this.point.colidesWith(lifeFormList[i].point)) {
var choice = this.makeChoice();
if(choice == 1) {
if(!this.fight() && lifeFormList[i].fight()) {
this.die();
continue;
}
if(this.fight() && !lifeFormList[i].fight()) {
lifeFormList[i].die();
continue;
}
}
if(choice == 2) {
if(this.multiply() || lifeFormList[i].multiply()) {
var child = new LifeForm();
child.point = this.point;
child.color = this.color;
child.point.moveRandomly();
console.log('multiply');
break;
}
}
}
}
}
if(this.randomlyDie()) {
this.die();
}
this.point.moveRandomly();
},
/**
* 1 = fight
* 2 = multiply
* 3 = pass
*/
makeChoice : function() {
var choice = Math.random()*10;
return choice > 7.5 ? 1 : choice > 5 ? 2 : 3;
},
fight : function() {
return Math.random() * 10 > 5;
},
multiply : function() {
return Math.random()*10 > 8;
},
randomlyDie : function() {
return Math.random() * 1000000000 > 999999998;
},
die : function() {
console.log('die');
lifeFormList.pop(this);
}
}
//window.onload = function(){
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context = canvas.getContext('2d');
for(var i = 0; i <= 200; i++) {
new LifeForm();
}
// life loop
setInterval(function(){
for(var i in lifeFormList) {
lifeFormList[i].takeTurn();
}
},1000/30);
// render loop
setInterval(function(){
context.clearRect(0,0,canvas.width,canvas.height);
for(var i in lifeFormList) {
context.fillStyle = lifeFormList[i].color;
context.fillRect(lifeFormList[i].point.x,lifeFormList[i].point.y,lifeFormSquareSize,lifeFormSquareSize);
}
},1000/30)
//}
</script>
</body>
</html>
Fighting for peace is declaring war on war. If you want peace be peaceful.
Verahta
Posts: 440 Joined: Wed Aug 24, 2011 1:50 am
Post
by Verahta » Tue Aug 19, 2014 12:15 am
Awesome! After I wrap my head around it some mi=ore I'm going to make one too. Changing the size is cool.
"In order to understand recursion, one must first understand recursion".
Chris
Posts: 1580 Joined: Wed Sep 30, 2009 7:22 pm
Post
by Chris » Tue Aug 19, 2014 12:32 am
Code: Select all
<html>
<head>
<style type="text/css">
*{ padding: 0px; margin: 0px; background: #000; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
lifeFormSquareSize = 6;
var Point = function(x,y) {
this.x = x || parseInt(Math.random() * (window.innerWidth/6));
this.y = y || parseInt(Math.random() * (window.innerHeight/6));
return this;
}
Point.prototype.constructor = Point;
Point.prototype = {
x : 0,
y : 0,
colidesWith : function(point) {
return point.x == this.x && point.y == this.y;
},
moveRandomly : function() {
var randomX = Math.random() * 10;
var randomY = Math.random() * 10;
var displaceX = parseInt(Math.random()*lifeFormSquareSize);
var displaceY = parseInt(Math.random()*lifeFormSquareSize);
this.x = parseInt(randomX > 7.5 ? (this.x+displaceX) : (randomX > 5 ? (this.x-displaceX) : this.x));
this.y = parseInt(randomY > 7.5 ? (this.y+displaceY) : (randomY > 5 ? (this.y-displaceY) : this.y));
}
}
var lifeFormList = [];
var LifeForm = function() {
lifeFormList.push(this);
this.point = new Point();
this.color = '#' +(Math.random()*0xFFFFFF<<0).toString(16);
return this;
}
LifeForm.prototype.contructor = LifeForm;
LifeForm.prototype = {
color : '#000000',
point : null,
takeTurn : function() {
for(var i in lifeFormList) {
if(lifeFormList[i] !== this) {
if(this.point.colidesWith(lifeFormList[i].point)) {
var choice = this.makeChoice();
if(choice == 1) {
if(this.fight() && lifeFormList[i].fight()) {
if(Math.random() * 2 < 0.5 ) {
this.die();
} else if(Math.random() * 2 < 1 ) {
lifeFormList[i].die();
}
continue;
}
}
if(choice == 2) {
if(this.multiply() && lifeFormList[i].multiply()) {
var child = new LifeForm();
child.point = this.point;
child.color = this.color;
child.point.moveRandomly();
new Born(this.point);
console.log('multiply');
break;
}
}
if(choice == 3) {
this.color = '#' +(Math.random()*0xFFFFFF<<0).toString(16);
}
}
}
}
if(this.randomlyDie()) {
this.die();
}
this.point.moveRandomly();
},
/**
* 1 = fight
* 2 = multiply
* 3 = pass
*/
makeChoice : function() {
var choice = Math.random()*10;
return choice > 7.5 ? 1 : choice > 5 ? 2 : 3;
},
fight : function() {
return Math.random() * 10 > 5;
},
multiply : function() {
return Math.random()*10 > 8;
},
randomlyDie : function() {
return Math.random() * 1000000000 > 999999998;
},
die : function() {
console.log('die');
lifeFormList.pop(this);
new Die(this.point);
}
}
var dieList = [];
var Die = function(point) {
var _point = new Point(point.x,point.y);
this.point = _point;
dieList.push(this);
var _this = this;
var textInterval = setInterval(function(){
_this.point.y--;
},10);
setTimeout(function(){
clearInterval(textInterval);
dieList.pop(_this);
},500);
}
var bornList = []
var Born = function(point) {
var _point = new Point(point.x,point.y);
this.point = _point;
bornList.push(this);
var _this = this;
var textInterval = setInterval(function(){
_this.point.y--;
},10);
setTimeout(function(){
clearInterval(textInterval);
bornList.pop(_this);
},500);
}
//window.onload = function(){
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context = canvas.getContext('2d');
for(var i = 0; i <= 500; i++) {
new LifeForm();
}
// life loop
setInterval(function(){
for(var i in lifeFormList) {
lifeFormList[i].takeTurn();
}
},10);
// render loop
setInterval(function(){
context.clearRect(0,0,canvas.width,canvas.height);
for(var i in lifeFormList) {
context.fillStyle = lifeFormList[i].color;
context.fillRect(lifeFormList[i].point.x,lifeFormList[i].point.y,lifeFormSquareSize,lifeFormSquareSize);
}
for(var i in bornList) {
context.fillStyle = '#00FF00';
context.font = '10pt Arial';
context.fillText('BORN', bornList[i].point.x,bornList[i].point.y);
}
for(var i in dieList) {
context.fillStyle = '#FF0000';
context.font = '10pt Arial';
context.fillText('DIED', dieList[i].point.x,dieList[i].point.y);
}
},1000/60)
//}
</script>
</body>
</html>
Fighting for peace is declaring war on war. If you want peace be peaceful.