Skip to content

Instantly share code, notes, and snippets.

@junpeitsuji
Created November 23, 2013 12:51
Show Gist options
  • Save junpeitsuji/7614263 to your computer and use it in GitHub Desktop.
Save junpeitsuji/7614263 to your computer and use it in GitHub Desktop.
Boids シミュレーション をブラウザで
<!DOCTYPE html>
<title>Boids Simulation</title>
<h1>Boids Simulation</h1>
<canvas id="canvas" width="640" height="480"></canvas>
<style>
/**
* html body に設定される自然な
* margin padding を除去する
*/
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
canvas {
background-color: #CCC;
}
</style>
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
$(function() {
// コンテキストを取得する関数
function getCtx() {
var canvas = document.getElementById('canvas');
return canvas.getContext('2d');
};
// グローバル変数の初期化
var width = canvas.width;
var height = canvas.height;
var canvasRect = canvas.getBoundingClientRect()
var target = {
x: 0,
y: 0
};
// 制限速度
var MAXSPEED = 5;
// boid の個体数
var numOfBoids = 30;
// boid の個体を管理する配列
var boids = new Array(numOfBoids);
// 初期処理
for(var i=0; i<numOfBoids; i++){
boids[i] = {
x: width/2,
y: height/2,
vx: 0,
vy: 0
};
}
var Boids = {
rule1: function(i){ // すべてのBoidは群の中心に向かおうとする
var cx = 0;
var cy = 0;
for( var j = 0; j < numOfBoids; j++ ){
if( i != j ){
cx += boids[ j ].x;
cy += boids[ j ].y;
}
}
cx /= numOfBoids - 1;
cy /= numOfBoids - 1;
boids[ i ].vx += ( cx - boids[ i ].x ) / 1000;
boids[ i ].vy += ( cy - boids[ i ].y ) / 1000;
},
rule2: function(i){ // 他の個体と距離をとろうとする
var vx = 0;
var vy = 0;
for( var j = i + 1; j < numOfBoids; j++ ){
var dx = boids[ j ].x - boids[ i ].x;
var dy = boids[ j ].y - boids[ i ].y;
var dist = Math.sqrt( dx * dx + dy * dy );
if( dist < 15 ){
dist += 0.001;
vx -= dx / dist;
vy -= dy / dist;
}
}
boids[ i ].vx += vx;
boids[ i ].vy += vy;
},
rule3: function(i){ // 他の個体と向きと速度を合わせようとする
var pvx = 0;
var pvy = 0;
for( var j = 0; j < numOfBoids; j++ ){
if( i != j ){
pvx += boids[ j ].vx;
pvy += boids[ j ].vy;
}
}
pvx /= numOfBoids - 1;
pvy /= numOfBoids - 1;
boids[ i ].vx += ( pvx - boids[ i ].vx ) / 10;
boids[ i ].vy += ( pvy - boids[ i ].vy ) / 10;
},
rule4: function(i){
},
rule5: function(i){
var dx = target.x - boids[ i ].x;
var dy = target.y - boids[ i ].y;
var dist = Math.sqrt( dx * dx + dy * dy );
boids[ i ].vx += ( target.x - boids[ i ].x ) / 500;
if( boids[ i ].vx * ( target.x - boids[ i ].x ) < 0 ){
boids[ i ].vx += ( target.x - boids[ i ].x ) / 500;
}
boids[ i ].vy += ( target.y - boids[ i ].y ) / 500;
if( boids[ i ].vy * ( target.y - boids[ i ].y ) < 0 ){
boids[ i ].vy += ( target.x - boids[ i ].y ) / 500;
}
}
}
// メインの実行
main();
// クリック処理
$('canvas').click( function(event){
target.x = event.pageX - canvasRect.left;
target.y = event.pageY - canvasRect.top;
console.log(target.x);
});
// ここからメイン
function main(){
var ctx = getCtx();
ctx.clearRect(0, 0, width, height);
draw();
update();
setTimeout( main, 20 );
}
function draw(){
var ctx = getCtx();
// boid の描画
boids.forEach(function(boid){
fillOval(ctx, boid.x, boid.y, 10, 'rgba(192, 80, 77, 0.7)');
});
// target の描画
fillOval(ctx, target.x, target.y, 20, 'rgba(192, 80, 77, 0.7)');
}
function update(){
for(var i=0; i<numOfBoids; i++){
Boids.rule1(i);
Boids.rule2(i);
Boids.rule3(i);
Boids.rule4(i);
Boids.rule5(i);
//boids[i].x = boids[i].x + 0.1*(target.x-boids[i].x);
//boids[i].y = boids[i].y + 0.1*(target.y-boids[i].y);
// 速さを制限する
var l = Math.sqrt( boids[ i ].vx * boids[ i ].vx + boids[ i ].vy * boids[ i ].vy );
if( l > MAXSPEED ){
boids[ i ].vx *= MAXSPEED / l;
boids[ i ].vy *= MAXSPEED / l;
}
// 位置の更新
boids[ i ].x += boids[ i ].vx;
boids[ i ].y += boids[ i ].vy;
}
}
// 円を描く
function fillOval(ctx, x, y, radious, fillStyle){
ctx.fillStyle = fillStyle;
ctx.beginPath();
ctx.arc(x, y, radious, 0, Math.PI*2, false);
ctx.fill();
}
});
</script>
@SS1031
Copy link

SS1031 commented Nov 23, 2013

いいですね~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment