Skip to content

Instantly share code, notes, and snippets.

@man-oi
Created September 17, 2012 10:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save man-oi/3736630 to your computer and use it in GitHub Desktop.
Save man-oi/3736630 to your computer and use it in GitHub Desktop.
Simple blods algorithm used to make strange generative patters. By Tim Holman @twholman
<canvas id='c'></canvas>
var width = window.innerWidth - 8, height = window.innerHeight - 8, timerID = 0, c2 = document.getElementById('c'), ctx = c2.getContext('2d');
ctx.globalCompositeOperation = 'source-over';
c2.width = width;
c2.height = height;
var speed = 10;
var size = 1;
var boids = [];
var points = new Array();
var totalBoids = 7;
var pointCount = 0;
var init = function(){
for (var i = 0; i < totalBoids; i++) {
boids.push({
x: Math.random() * width,
y: Math.random() * height,
v: {
x: Math.random() * 2 - 1,
y: Math.random() * 2 - 1
}
});
}
setInterval(update, 40);
}
var calculateDistance = function(v1, v2){
x = Math.abs(v1.x - v2.x);
y = Math.abs(v1.y - v2.y);
return Math.sqrt((x * x) + (y * y));
}
var checkWallCollisions = function(index){
if (boids[index].x > width) {
boids[index].x = 0;
}
else
if (boids[index].x < 0) {
boids[index].x = width;
}
if (boids[index].y > height) {
boids[index].y = 0;
}
else
if (boids[index].y < 0) {
boids[index].y = height;
}
}
var addForce = function(index, force){
boids[index].v.x += force.x;
boids[index].v.y += force.y;
magnitude = calculateDistance({
x: 0,
y: 0
}, {
x: boids[index].v.x,
y: boids[index].v.y
});
boids[index].v.x = boids[index].v.x / magnitude;
boids[index].v.y = boids[index].v.y / magnitude;
}
//This should be in multiple functions, but this will
//save tons of looping - Gross!
var applyForces = function(index){
percievedCenter = {
x: 0,
y: 0
};
flockCenter = {
x: 0,
y: 0
};
percievedVelocity = {
x: 0,
y: 0
};
count = 0;
for (var i = 0; i < boids.length; i++) {
if (i != index) {
//Allignment
dist = calculateDistance(boids[index], boids[i]);
//console.log(dist);
if (dist > 0 && dist < 50) {
count++;
//Alignment
percievedCenter.x += boids[i].x;
percievedCenter.y += boids[i].y;
//Cohesion
percievedVelocity.x += boids[i].v.x;
percievedVelocity.y += boids[i].v.y;
//Seperation
if (calculateDistance(boids[i], boids[index]) < 10) {
flockCenter.x -= (boids[i].x - boids[index].x);
flockCenter.y -= (boids[i].y - boids[index].y);
}
}
}
}
if (count > 0) {
percievedCenter.x = percievedCenter.x / count;
percievedCenter.y = percievedCenter.y / count;
percievedCenter.x = (percievedCenter.x - boids[index].x) / 400;
percievedCenter.y = (percievedCenter.y - boids[index].y) / 400;
percievedVelocity.x = percievedVelocity.x / count;
percievedVelocity.y = percievedVelocity.y / count;
flockCenter.x /= count;
flockCenter.y /= count;
}
addForce(index, percievedCenter);
addForce(index, percievedVelocity);
addForce(index, flockCenter);
}
var update = function(){
for (var i = 0; i < boids.length; i++) {
var d, dx, dy,j;
//Draw boid
ctx.strokeStyle = "rgba(0, 0 , 0, 0.5)";
ctx.lineWidth = size;
ctx.beginPath();
ctx.moveTo(boids[i].x, boids[i].y);
boids[i].x += boids[i].v.x * speed;
boids[i].y += boids[i].v.y * speed;
applyForces(i);
ctx.lineTo(boids[i].x, boids[i].y);
ctx.stroke();
points.push( [ boids[i].x, boids[i].y ] );
//Web
ctx.strokeStyle = "rgba(0, 0 , 0, 0.1)";
for (j = 0; j < points.length; j++)
{
dx = points[j][0] - points[pointCount][0];
dy = points[j][1] - points[pointCount][1];
d = dx * dx + dy * dy;
if (d < 2500 && Math.random() > 0.9)
{
ctx.beginPath();
ctx.moveTo( points[pointCount][0], points[pointCount][1]);
ctx.lineTo( points[j][0], points[j][1]);
ctx.stroke();
}
}
pointCount++;
checkWallCollisions(i);
}
}
//Gui uses this to clear the canvas
var clearCanvas = function(){
ctx.fillStyle = 'rgba(255, 255, 255, 1.0)';
ctx.beginPath();
ctx.rect(0, 0, width, height);
ctx.closePath();
ctx.fill();
}
init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment