boids/boids.mjs

80 lines
2.1 KiB
JavaScript
Raw Normal View History

2020-05-04 15:17:55 +00:00
import Vector from './vector.mjs';
const meanPos = new Vector(0, 0);
const meanVel = new Vector(0, 0);
const repelForce = new Vector(0, 0);
2020-05-04 15:17:55 +00:00
export const update = (boids, params, width, height, time) =>
2020-05-04 15:17:55 +00:00
{
const boidsSize = boids.length;
for (let i = 0; i < boidsSize; ++i)
2020-05-04 15:17:55 +00:00
{
const me = boids[i];
2020-05-04 15:17:55 +00:00
meanPos.reset();
meanVel.reset();
repelForce.reset();
let visibleSize = 0;
2020-05-04 15:17:55 +00:00
for (let j = 0; j < boidsSize; ++j)
2020-05-04 15:17:55 +00:00
{
if (i != j)
{
const you = boids[j];
const dist = Vector.distSquared(me.pos, you.pos);
if (dist < params.visibleDist * params.visibleDist)
{
meanPos.add(you.pos);
meanVel.add(you.vel);
visibleSize += 1;
if (dist < params.closeDist * params.closeDist)
{
repelForce.add(me.pos).sub(you.pos);
}
}
}
2020-05-04 15:17:55 +00:00
}
// Attract towards center of visible flock
if (visibleSize >= 1)
2020-05-04 15:17:55 +00:00
{
me.vel.add(meanPos.div(visibleSize)
.sub(me.pos)
.mul(params.centerAccel));
2020-05-04 15:17:55 +00:00
}
// Attract toward center of screen if out of bounds
if (me.pos.x < width * -.4 || me.pos.x > width * .4 ||
me.pos.y < height * -.4 || me.pos.y > height * .4)
{
me.vel.addMul(me.pos, -params.boundsAccel);
}
2020-05-04 15:17:55 +00:00
// Repel away from close boids
me.vel.add(repelForce.mul(params.repelAccel));
2020-05-04 15:17:55 +00:00
// Match other boids velocity
if (visibleSize >= 1)
2020-05-04 15:17:55 +00:00
{
me.vel.add(meanVel.div(visibleSize)
.sub(me.vel)
.mul(params.matchAccel));
2020-05-04 15:17:55 +00:00
}
// Do not surpass maximum speed
const speed = me.vel.normSquared();
2020-05-04 15:17:55 +00:00
if (speed > params.maxSpeed * params.maxSpeed)
{
me.vel.div(Math.sqrt(speed)).mul(params.maxSpeed);
2020-05-04 15:17:55 +00:00
}
// Integrate speed
me.pos.addMul(me.vel, time);
2020-05-04 15:17:55 +00:00
}
};