xxxxxxxxxx
232
class Particle extends p5.Vector {
static Debug = true;
static _particles = {};
static createRandom() {
throw new Error("Not implemented");
}
static Get(num) {
const type = this.name;
const dict = Particle._particles;
if (!(type in dict)) dict[type] = [];
const array = Particle._particles[type];
num = Math.max(0, Math.min(num, array.length));
return array[num];
}
static get All() {
const type = this.name;
const dict = Particle._particles;
if (!(type in dict)) dict[type] = [];
return Particle._particles[type];
}
static balance(count) {
if (Number.isNaN(count) || count < 0 || count >= 100) return;
const type = this.name;
const dict = Particle._particles;
if (!(type in dict)) dict[type] = [];
const array = Particle._particles[type];
let maxLoops = 10e3;
while (array.length !== count && maxLoops-- > 0) {
if (array.length < count) this.createRandom().add();
else if (array.length > count) array.pop().remove();
}
}
static add(particle) {
const dict = Particle._particles;
const type = particle.constructor.name;
if (!(type in dict)) dict[type] = [];
if (!dict[type].includes(particle)) {
dict[type].push(particle);
return true;
} else return false;
}
static *[Symbol.iterator]() {
const dict = Particle._particles;
const type = this.name;
if (type in dict) {
for (const particle of dict[type]) {
yield particle;
}
}
}
get isActive() {
if (this._isActive === undefined) this.isActive = false;
return this._isActive;
}
set isActive(value) {
this._isActive = value;
this.matterBody.isSensor = !value;
}
get velocity() {
return new p5.Vector(
this.matterBody.velocity.x,
this.matterBody.velocity.y
);
}
static STATES = {};
isState(statename) {
if (Array.isArray(statename))
return statename.some((state) => this.isState(state));
else return this.state === this.constructor.STATES[statename];
}
setState(statename) {
this.state = this.constructor.STATES[statename] ?? -1;
}
constructor(x, y, options) {
super(x, y);
const {
radius = 0,
angle = 0,
maxForce = 2,
maxSpeed = 12,
velocity = p5.Vector.Null,
mass = radius,
frictionAir = 0.0008 * radius,
friction = 0,
restituion = 0.8,
} = options;
delete options.radius;
delete options.angle;
delete options.maxForce;
delete options.maxSpeed;
this.matterBody = Matter.Bodies.circle(x, y, radius, {
options,
velocity: velocity.matterVector,
mass: mass,
frictionAir: frictionAir,
friction: friction,
restitution: restituion,
});
this.state = -1;
this.force = p5.Vector.Null;
this.radius = radius;
this.angle = radians(angle);
this.maxSpeed = maxSpeed;
this.maxForce = maxForce;
this.drawQueue = [];
}
add() {
if (Particle.add(this))
Matter.Composite.add(MATTER_ENGINE.world, this.matterBody);
this.isActive = true;
return this;
}
remove() {
Matter.Composite.remove(MATTER_ENGINE.world, this.matterBody);
}
wrapBounds() {
const [{ x, y }, r] = [this, this.radius];
const trsh = 0.2; //treshhold
if (x < 0 - r - trsh) this.x = CANVAS_WIDTH + r;
else if (x > CANVAS_WIDTH + r + trsh) this.x = -r;
if (y < 0 - r - trsh) this.y = CANVAS_HEIGHT + r;
else if (y > CANVAS_HEIGHT + r + trsh) this.y = -r;
}
render() {
if (!this.isActive) return;
if (!this.matterBody.isStatic) this.move();
push();
translate(this.x, this.y);
rotate(this.angle);
this.draw();
pop();
for (let i = 0; i < this.drawQueue.length; i++) {
const obj = this.drawQueue[i];
if (--obj.frames > 0) {
obj.drawFunc();
} else if (this.drawQueue.length > 1) {
this.drawQueue[i--] = this.drawQueue.pop();
} else {
this.drawQueue.pop();
}
print(this.drawQueue.length);
}
}
move() {
this.x = this.matterBody.position.x;
this.y = this.matterBody.position.y;
const velocity = this.velocity.limit(this.maxSpeed);
this.wrapBounds();
Matter.Body.setVelocity(this.matterBody, velocity.matterVector);
Matter.Body.setPosition(this.matterBody, this.matterVector);
}
applySteer(desired) {
this.applyForce(p5.Vector.sub(desired, this.velocity));
}
applyForce(force, applyTimescale = true) {
force.limit(this.maxForce);
force.setMag(force.mag() * TIMESCALE);
Matter.Body.applyForce(
this.matterBody,
this.matterVector,
force.matterVector
);
}
setPosition(x, y) {
this.x = x;
this.y = y;
Matter.Body.setPosition(this.matterBody, this.matterVector);
}
drawForNumberOfFrames(frames, drawFunc) {
if (this.drawQueue.length > 10) {
return;
}
this.drawQueue.push({
drawFunc: drawFunc,
frames: frames,
});
}
draw() {
circle(0, 0, this.radius * 2);
}
dist(particle) {
// Distance from both outer rims of circular particles.
return super.dist(particle) - (particle.radius ?? 0) - (this.radius ?? 0);
}
}