Skip to content

Instantly share code, notes, and snippets.

@edom18
Created February 19, 2013 00:19
Show Gist options
  • Save edom18/4981959 to your computer and use it in GitHub Desktop.
Save edom18/4981959 to your computer and use it in GitHub Desktop.
forked: Flocking Boids
body { background-color: #FFFFFF; font: 30px sans-serif; margin:0px;}
<canvas id='c'></canvas>
// forked from tholman's "Flocking Boids" http://jsdo.it/tholman/eVUR
var width = window.innerWidth - 8, height = window.innerHeight - 8, timerID = 0, c2 = document.getElementById('c'), ctx = c2.getContext('2d');
c2.width = width;
c2.height = height;
var speed = 10;
var size = 8;
var boids = [];
var totalBoids = 150;
var init = function(){
//指定数のboidを生成(150個)
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
},
c: 'rgba(' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ', 1.0)'
});
}
setInterval(update, 40);
}
//2点間の距離
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;
}
}
//算出された値を対象boidに加算
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; //平均値を出すために、"近くの"boidの数をカウント
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]) < 12) {
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(){
clearCanvas();
for (var i = 0; i < boids.length; i++) {
//Draw boid
ctx.beginPath();
ctx.strokeStyle = boids[i].c;
ctx.lineWidth = size;
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();
ctx.fill();
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