Reduce memory usage to improve GC performance
This commit is contained in:
parent
11ffc81848
commit
9c9afa2409
94
boids.mjs
94
boids.mjs
|
@ -1,79 +1,75 @@
|
||||||
import Vector from './vector.mjs';
|
import Vector from './vector.mjs';
|
||||||
|
|
||||||
const findNeighbors = (boids, boid, radius) =>
|
const meanPos = new Vector(0, 0);
|
||||||
{
|
const meanVel = new Vector(0, 0);
|
||||||
const neighbors = [];
|
const repelForce = new Vector(0, 0);
|
||||||
|
|
||||||
for (let otherBoid of boids)
|
|
||||||
{
|
|
||||||
if (boid != otherBoid)
|
|
||||||
{
|
|
||||||
const dist = boid.pos.sub(otherBoid.pos).normSquared();
|
|
||||||
|
|
||||||
if (dist < radius * radius)
|
|
||||||
{
|
|
||||||
neighbors.push(otherBoid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return neighbors;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const update = (boids, params, time) =>
|
export const update = (boids, params, time) =>
|
||||||
{
|
{
|
||||||
for (let boid of boids)
|
const boidsSize = boids.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < boidsSize; ++i)
|
||||||
{
|
{
|
||||||
const visible = findNeighbors(boids, boid, params.visibleDist);
|
const me = boids[i];
|
||||||
const close = findNeighbors(boids, boid, params.closeDist);
|
|
||||||
|
|
||||||
// Attract towards center of visible flock
|
meanPos.reset();
|
||||||
const center = new Vector(0, 0);
|
meanVel.reset();
|
||||||
|
repelForce.reset();
|
||||||
|
|
||||||
for (let otherBoid of visible)
|
let visibleSize = 0;
|
||||||
|
|
||||||
|
for (let j = 0; j < boidsSize; ++j)
|
||||||
{
|
{
|
||||||
center.addMut(otherBoid.pos);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visible.length >= 1)
|
// Attract towards center of visible flock
|
||||||
|
if (visibleSize >= 1)
|
||||||
{
|
{
|
||||||
center.divMut(visible.length);
|
me.vel.add(meanPos.div(visibleSize)
|
||||||
boid.vel.addMut(center.sub(boid.pos).mul(params.centerAccel));
|
.sub(me.pos)
|
||||||
|
.mul(params.centerAccel));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attract toward center of screen
|
// Attract toward center of screen
|
||||||
boid.vel.addMut(boid.pos.mul(-0.01));
|
me.vel.addMul(me.pos, -0.01);
|
||||||
|
|
||||||
// Repel away from close boids
|
// Repel away from close boids
|
||||||
for (let otherBoid of close)
|
me.vel.add(repelForce.mul(params.repelAccel));
|
||||||
{
|
|
||||||
boid.vel.addMut(boid.pos
|
|
||||||
.sub(otherBoid.pos)
|
|
||||||
.mul(params.repelAccel));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match other boids’ velocity
|
// Match other boids’ velocity
|
||||||
const velocity = new Vector(0, 0);
|
if (visibleSize >= 1)
|
||||||
|
|
||||||
for (let otherBoid of visible)
|
|
||||||
{
|
{
|
||||||
velocity.addMut(otherBoid.vel);
|
me.vel.add(meanVel.div(visibleSize)
|
||||||
}
|
.sub(me.vel)
|
||||||
|
.mul(params.matchAccel));
|
||||||
if (visible.length >= 1)
|
|
||||||
{
|
|
||||||
velocity.divMut(visible.length);
|
|
||||||
boid.vel.addMut(velocity.sub(boid.vel).mul(params.matchAccel));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not surpass maximum speed
|
// Do not surpass maximum speed
|
||||||
const speed = boid.vel.normSquared();
|
const speed = me.vel.normSquared();
|
||||||
|
|
||||||
if (speed > params.maxSpeed * params.maxSpeed)
|
if (speed > params.maxSpeed * params.maxSpeed)
|
||||||
{
|
{
|
||||||
boid.vel.divMut(Math.sqrt(speed)).mulMut(params.maxSpeed);
|
me.vel.div(Math.sqrt(speed)).mul(params.maxSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
boid.pos.addMut(boid.vel.mul(time));
|
// Integrate speed
|
||||||
|
me.pos.addMul(me.vel, time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
24
draw.mjs
24
draw.mjs
|
@ -7,8 +7,13 @@ const boidShape = [
|
||||||
new Vector(2, 0),
|
new Vector(2, 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const boidShapeSize = boidShape.length;
|
||||||
|
const transformed = new Vector(0, 0);
|
||||||
|
|
||||||
export const boids = (activeBoids, params, ctx, width, height, center) =>
|
export const boids = (activeBoids, params, ctx, width, height, center) =>
|
||||||
{
|
{
|
||||||
|
const boidsSize = activeBoids.length;
|
||||||
|
|
||||||
ctx.clearRect(0, 0, width, height);
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
|
||||||
// // Draw each boid’s visibility and proximity zones
|
// // Draw each boid’s visibility and proximity zones
|
||||||
|
@ -75,24 +80,31 @@ export const boids = (activeBoids, params, ctx, width, height, center) =>
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.fillStyle = 'black';
|
ctx.fillStyle = 'black';
|
||||||
|
|
||||||
for (let boid of activeBoids)
|
for (let i = 0; i < boidsSize; ++i)
|
||||||
{
|
{
|
||||||
|
const boid = activeBoids[i];
|
||||||
const angle = boid.vel.angle();
|
const angle = boid.vel.angle();
|
||||||
let isFirst = true;
|
let isFirst = true;
|
||||||
|
|
||||||
for (let point of boidShape)
|
for (let j = 0; j < boidShapeSize; ++j)
|
||||||
{
|
{
|
||||||
const trans = boid.pos.add(center)
|
transformed.x = boidShape[j].x;
|
||||||
.add(point.rotate(angle).mul(params.radius))
|
transformed.y = boidShape[j].y;
|
||||||
|
|
||||||
|
transformed
|
||||||
|
.rotate(angle)
|
||||||
|
.mul(params.radius)
|
||||||
|
.add(center)
|
||||||
|
.add(boid.pos);
|
||||||
|
|
||||||
if (isFirst)
|
if (isFirst)
|
||||||
{
|
{
|
||||||
ctx.moveTo(trans.x, trans.y);
|
ctx.moveTo(transformed.x, transformed.y);
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ctx.lineTo(trans.x, trans.y);
|
ctx.lineTo(transformed.x, transformed.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
52
vector.mjs
52
vector.mjs
|
@ -7,23 +7,20 @@ class Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
add(vector)
|
add(vector)
|
||||||
{
|
|
||||||
return new Vector(this.x + vector.x, this.y + vector.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
addMut(vector)
|
|
||||||
{
|
{
|
||||||
this.x += vector.x;
|
this.x += vector.x;
|
||||||
this.y += vector.y;
|
this.y += vector.y;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub(vector)
|
addMul(vector, scalar)
|
||||||
{
|
{
|
||||||
return new Vector(this.x - vector.x, this.y - vector.y);
|
this.x += vector.x * scalar;
|
||||||
|
this.y += vector.y * scalar;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
subMut(vector)
|
sub(vector)
|
||||||
{
|
{
|
||||||
this.x -= vector.x;
|
this.x -= vector.x;
|
||||||
this.y -= vector.y;
|
this.y -= vector.y;
|
||||||
|
@ -31,11 +28,6 @@ class Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
mul(scalar)
|
mul(scalar)
|
||||||
{
|
|
||||||
return new Vector(this.x * scalar, this.y * scalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
mulMut(scalar)
|
|
||||||
{
|
{
|
||||||
this.x *= scalar;
|
this.x *= scalar;
|
||||||
this.y *= scalar;
|
this.y *= scalar;
|
||||||
|
@ -47,20 +39,16 @@ class Vector
|
||||||
return this.mul(1 / scalar);
|
return this.mul(1 / scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
divMut(scalar)
|
|
||||||
{
|
|
||||||
return this.mulMut(1 / scalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
rotate(angle)
|
rotate(angle)
|
||||||
{
|
{
|
||||||
const cos = Math.cos(angle);
|
const cos = Math.cos(angle);
|
||||||
const sin = Math.sin(angle);
|
const sin = Math.sin(angle);
|
||||||
|
const nextX = cos * this.x - sin * this.y;
|
||||||
|
const nextY = cos * this.y + sin * this.x;
|
||||||
|
|
||||||
return new Vector(
|
this.x = nextX;
|
||||||
cos * this.x - sin * this.y,
|
this.y = nextY;
|
||||||
cos * this.y + sin * this.x,
|
return this;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
angle()
|
angle()
|
||||||
|
@ -72,6 +60,26 @@ class Vector
|
||||||
{
|
{
|
||||||
return this.x * this.x + this.y * this.y;
|
return this.x * this.x + this.y * this.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static distSquared(lhs, rhs)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(lhs.x - rhs.x) * (lhs.x - rhs.x)
|
||||||
|
+ (lhs.y - rhs.y) * (lhs.y - rhs.y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset()
|
||||||
|
{
|
||||||
|
this.x = 0;
|
||||||
|
this.y = 0;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone()
|
||||||
|
{
|
||||||
|
return new Vector(this.x, this.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Vector;
|
export default Vector;
|
||||||
|
|
Loading…
Reference in New Issue