Created
November 23, 2013 12:51
-
-
Save junpeitsuji/7614263 to your computer and use it in GitHub Desktop.
Boids シミュレーション をブラウザで
This file contains hidden or 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
<!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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
いいですね~