執筆者: кемо
最終更新: 2024/10/24
particle lifeとはシンプルな人工生命の1つで、シンプルなルールで複雑な動きを見られるのが魅力です。シンプル故にコードも簡単なので、初心者にもオススメかも。
概要で「人工生命」と大げさなことを言いましたが、どっちかというと粒子シミュレーションです。要はオートマトンや遺伝的アルゴリズムとは関係ないので、とてもシンプル。
このシミュレーションで計算されるのは粒子同士にはたらく力の大きさとなります。コードを見てもらったほうが早いと思うので,さっそくコードの解説に移ります.
まずは粒子の定義から.クラスを使えばもっとスッキリ書けますが,今回は構造体を使います.
2次元座標のほかに,x,y方向それぞれの速度vx,vy,粒子の色であるcolorを持っています.
function particle(x,y,c){
return {"x":x, "y":y, "vx":0, "vy":0, "color":c}
}
これは指定のパーティクル構造体を返す関数です.適切な関数名はadd_particleでしょうか......
function create(number, color){
group = [];
for(let i=0;i<number;i++){
group.push(particle(random(canvas.width), random(canvas.height), color));
particles.push(group[i]);
}
all_particle.push(group)
return group;
}
これは,先ほどのparticle関数を用いてnumber個の粒子を生成して,配列に格納し,さらにその配列を配列に格納する関数です.構造としては,all[group[particle,particle,...]...]的な感じです.
function draw(x,y,c,s){
graphic.fillStyle=c;
graphic.fillRect(x,y,s,s);
}
function draw_particle(x,y,c,s){
graphic.fillStyle=c;
graphic.beginPath();
graphic.arc(x, y, s, 0, 2 * Math.PI);
graphic.closePath();
graphic.fill();
}
描画用の関数2つです.特筆すべきことはありませんね.
function rule(particle1, particle2, G){
let fx,fy,a,b,dx,dy,d,F;
for(let i=0;i<particle1.length;i++){
fx = 0;
fy = 0;
for(let j=0;j<particle2.length;j++){
a = particle1[i];
b = particle2[j];
dx = a.x - b.x;
dy = a.y - b.y;
d = Math.sqrt(dx*dx + dy*dy)
if(d>5 && d<40){
F = G * 1/d;
fx += (F * dx);
fy += (F * dy);
}
else if(d<=5){
F = 0.3 * d;
fx += (F * dx);
fy += (F * dy);
}
}
a.vx = (a.vx + fx)*0.2;
a.vy = (a.vy + fy)*0.2;
if(a.x<0||a.x>canvas.width){
a.vx *= -100;
}
if(a.y<0||a.y>canvas.height){
a.vy *= -100;
}
a.x += a.vx;
a.y += a.vy;
}
}
このプログラムの核となる,粒子間の「法則」を定める関数です.particle1→particle2への力Gが引数となっています.Gが正なら斥力,負なら引力がはたらくことになり,それに従ってそれぞれの粒子が動きます.粒子同士が近づきすぎると,斥力がはたらくようになります.ちなみに,画面外に出た粒子には強制的に反対方向の力を与えることによって画面内に戻すゴリ押し仕様です.要改善なのでなにか考えてみてください.
大体この三要素ですね.これをsetInterval関数で回しています.流れを再確認します.
うまくいけばこんな感じになります.いろいろ試してみてください.
暇 つ ぶ し