chore: tidy

This commit is contained in:
cha0s 2021-01-04 00:24:47 -06:00
parent ccd31cf2be
commit 5fcf87c5cd
5 changed files with 251 additions and 197 deletions

View File

@ -10,6 +10,42 @@ const decorate = compose(
export default class Collider extends decorate(Trait) {
#collidesWithGroups;
#collisionEndActions;
#collisionStartActions;
#collisionGroup;
#doesNotCollideWith;
#isCollidingWith;
#isSensor;
constructor(...args) {
super(...args);
const {
collidesWithGroups,
collisionEndActions,
collisionGroup,
collisionStartActions,
isSensor,
} = this.params;
this.#collidesWithGroups = collidesWithGroups;
this.#collisionEndActions = collisionEndActions.length > 0
? new Actions(compile(collisionEndActions))
: undefined;
this.#collisionStartActions = collisionStartActions.length > 0
? new Actions(compile(collisionStartActions))
: undefined;
this.#collisionGroup = collisionGroup;
this.#doesNotCollideWith = [];
this.#isCollidingWith = [];
this.#isSensor = isSensor;
}
static behaviorTypes() {
return {
collidesWith: {
@ -123,28 +159,6 @@ export default class Collider extends decorate(Trait) {
};
}
constructor(entity, params, state) {
super(entity, params, state);
const {
collidesWithGroups,
collisionEndActions,
collisionGroup,
collisionStartActions,
isSensor,
} = this.params;
this._collidesWithGroups = collidesWithGroups;
this._collisionEndActions = collisionEndActions.length > 0
? new Actions(compile(collisionEndActions))
: undefined;
this._collisionStartActions = collisionStartActions.length > 0
? new Actions(compile(collisionStartActions))
: undefined;
this._collisionGroup = collisionGroup;
this._doesNotCollideWith = [];
this._isCollidingWith = [];
this._isSensor = isSensor;
}
destroy() {
this.releaseAllCollisions();
}
@ -195,23 +209,23 @@ export default class Collider extends decorate(Trait) {
}
get collisionGroup() {
return this._collisionGroup;
return this.#collisionGroup;
}
get collidesWithGroups() {
return this._collidesWithGroups;
return this.#collidesWithGroups;
}
get isCollidingWith() {
return this._isCollidingWith;
return this.#isCollidingWith;
}
isCollidingWithEntity(entity) {
return -1 !== this._isCollidingWith.indexOf(entity);
return -1 !== this.#isCollidingWith.indexOf(entity);
}
get isSensor() {
return this._isSensor;
return this.#isSensor;
}
pushCollisionTickingPromise(actions, other) {
@ -223,11 +237,11 @@ export default class Collider extends decorate(Trait) {
}
releaseAllCollisions() {
for (let i = 0; i < this._isCollidingWith.length; i++) {
const entity = this._isCollidingWith[i];
for (let i = 0; i < this.#isCollidingWith.length; i++) {
const entity = this.#isCollidingWith[i];
entity.emit('collisionEnd', this.entity);
}
this._isCollidingWith = [];
this.#isCollidingWith = [];
}
// eslint-disable-next-line class-methods-use-this
@ -243,21 +257,21 @@ export default class Collider extends decorate(Trait) {
return {
collisionEnd: (other) => {
const index = this._isCollidingWith.indexOf(other);
const index = this.#isCollidingWith.indexOf(other);
if (-1 !== index) {
this._isCollidingWith.splice(index, 1);
if (this._collisionEndActions) {
this.pushCollisionTickingPromise(this._collisionEndActions, other);
this.#isCollidingWith.splice(index, 1);
if (this.#collisionEndActions) {
this.pushCollisionTickingPromise(this.#collisionEndActions, other);
}
}
},
collisionStart: (other) => {
const index = this._isCollidingWith.indexOf(other);
const index = this.#isCollidingWith.indexOf(other);
if (-1 === index) {
this._isCollidingWith.push(other);
if (this._collisionStartActions) {
this.pushCollisionTickingPromise(this._collisionStartActions, other);
this.#isCollidingWith.push(other);
if (this.#collisionStartActions) {
this.pushCollisionTickingPromise(this.#collisionStartActions, other);
}
}
},
@ -276,25 +290,25 @@ export default class Collider extends decorate(Trait) {
if (!this.entity.isColliding || !entity.isColliding) {
return false;
}
if (-1 !== this._doesNotCollideWith.indexOf(entity)) {
if (-1 !== this.#doesNotCollideWith.indexOf(entity)) {
return false;
}
const {collisionGroup} = entity;
return -1 !== this._collidesWithGroups.indexOf(collisionGroup);
return -1 !== this.#collidesWithGroups.indexOf(collisionGroup);
},
doesNotCollideWith: (entity) => !this.entity.collidesWith(entity),
setDoesCollideWith: (entity) => {
const index = this._doesNotCollideWith.indexOf(entity);
const index = this.#doesNotCollideWith.indexOf(entity);
if (-1 !== index) {
this._doesNotCollideWith.splice(index, 1);
this.#doesNotCollideWith.splice(index, 1);
}
},
setDoesNotCollideWith: (entity) => {
if (-1 === this._doesNotCollideWith.indexOf(entity)) {
this._doesNotCollideWith.push(entity);
if (-1 === this.#doesNotCollideWith.indexOf(entity)) {
this.#doesNotCollideWith.push(entity);
}
},
};

View File

@ -7,6 +7,51 @@ const decorate = compose(
export default class Emitted extends decorate(Trait) {
#alphaStart;
#alphaEnd;
#force;
#mass;
#position;
#rotationStart;
#rotationAdd;
#scaleStart;
#scaleEnd;
#ttl;
#velocityAngle;
#velocityMagnitude;
constructor(...args) {
super(...args);
this.#alphaStart = new Range(this.params.alpha.start);
this.#alphaEnd = new Range(this.params.alpha.end);
this.#force = new Vector.Range(this.params.force);
this.#mass = this.params.mass;
if (null !== this.params.position) {
this.#position = new Vector.Range(this.params.position);
}
else {
this.#position = null;
}
this.#rotationStart = new Range(this.params.rotation.start);
this.#rotationAdd = new Range(this.params.rotation.add);
this.#scaleStart = new Range(this.params.scale.start);
this.#scaleEnd = new Range(this.params.scale.end);
this.#ttl = this.params.ttl;
this.#velocityAngle = new Range(this.params.velocity.angle);
this.#velocityMagnitude = new Range(this.params.velocity.magnitude);
}
static behaviorTypes() {
return {
particle: {
@ -88,27 +133,6 @@ export default class Emitted extends decorate(Trait) {
};
}
constructor(entity, params, state) {
super(entity, params, state);
this.alphaStart = new Range(this.params.alpha.start);
this.alphaEnd = new Range(this.params.alpha.end);
this.force = new Vector.Range(this.params.force);
this.mass = this.params.mass;
if (null !== this.params.position) {
this.position = new Vector.Range(this.params.position);
}
else {
this.position = null;
}
this.rotationStart = new Range(this.params.rotation.start);
this.rotationAdd = new Range(this.params.rotation.add);
this.scaleStart = new Range(this.params.scale.start);
this.scaleEnd = new Range(this.params.scale.end);
this.ttl = this.params.ttl;
this.velocityAngle = new Range(this.params.velocity.angle);
this.velocityMagnitude = new Range(this.params.velocity.magnitude);
}
get isTransientParticle() {
return !!this.params.transient;
}
@ -117,29 +141,29 @@ export default class Emitted extends decorate(Trait) {
return {
particle: () => {
const position = null === this.position ? null : this.position.value();
const force = this.force.value();
const position = null === this.#position ? null : this.#position.value();
const force = this.#force.value();
return {
alpha: {
start: this.alphaStart.value(),
end: this.alphaEnd.value(),
start: this.#alphaStart.value(),
end: this.#alphaEnd.value(),
},
force,
listed: this.params.listed,
mass: this.mass,
mass: this.#mass,
position,
rotation: {
start: this.rotationStart.value(),
add: this.rotationAdd.value(),
start: this.#rotationStart.value(),
add: this.#rotationAdd.value(),
},
scale: {
start: this.scaleStart.value(),
end: this.scaleEnd.value(),
start: this.#scaleStart.value(),
end: this.#scaleEnd.value(),
},
ttl: this.ttl,
ttl: this.#ttl,
velocity: {
angle: this.velocityAngle.value(),
magnitude: this.velocityMagnitude.value(),
angle: this.#velocityAngle.value(),
magnitude: this.#velocityMagnitude.value(),
},
};
},

View File

@ -13,6 +13,32 @@ const decorate = compose(
export default (latus) => class Emitter extends decorate(Trait) {
#emissions;
#emitter;
#onParticleDead;
#onParticleUpdate;
#particles;
#proton;
constructor(...args) {
super(...args);
this.#emissions = [];
this.#emitter = new Proton.Emitter();
this.#particles = {};
this.#proton = new Proton();
this.#proton.addEmitter(this.#emitter);
this.#onParticleDead = this.onParticleDead.bind(this);
this.#onParticleUpdate = this.onParticleUpdate.bind(this);
this.#emitter.bindEvent = true;
this.#emitter.addEventListener('PARTICLE_DEAD', this.#onParticleDead);
this.#emitter.addEventListener('PARTICLE_UPDATE', this.#onParticleUpdate);
}
static behaviorTypes() {
return {
emitParticleEntity: {
@ -68,18 +94,12 @@ export default (latus) => class Emitter extends decorate(Trait) {
};
}
constructor(entity, params, state) {
super(entity, params, state);
this.emissions = [];
this.emitter = new Proton.Emitter();
this.particles = {};
this.proton = new Proton();
this.proton.addEmitter(this.emitter);
this.onParticleDead = this.onParticleDead.bind(this);
this.onParticleUpdate = this.onParticleUpdate.bind(this);
this.emitter.bindEvent = true;
this.emitter.addEventListener('PARTICLE_DEAD', this.onParticleDead);
this.emitter.addEventListener('PARTICLE_UPDATE', this.onParticleUpdate);
emitParticleJson(json, emitter) {
const {fromResourceType: {Entity}} = resource(latus);
Entity.loadOrInstance(json).then((particle) => {
this.entity.emitParticleEntity(particle);
emitter.emit(particle);
});
}
gatherParticles() {
@ -97,32 +117,15 @@ export default (latus) => class Emitter extends decorate(Trait) {
const [key, particle] = paramParticles[i];
particles[key] = merge(particles[key] || {}, particle);
}
this.particles = particles;
}
// eslint-disable-next-line class-methods-use-this
onParticleDead(particle) {
if (particle.body.isTransientParticle) {
particle.body.destroy();
}
}
// eslint-disable-next-line class-methods-use-this
onParticleUpdate(particle) {
particle.body.setPosition([particle.p.x, particle.p.y]);
/* eslint-disable no-param-reassign */
particle.body.opacity = particle.alpha;
particle.body.visibleScale = [particle.scale, particle.scale];
particle.body.rotation = particle.rotation * PI_180;
/* eslint-enable no-param-reassign */
this.#particles = particles;
}
hooks() {
const hooks = {};
hooks.afterDestructionTickers = () => (elapsed) => {
this.tick(elapsed);
if (0 === this.emitter.particles.length) {
this.emitter.destroy();
if (0 === this.#emitter.particles.length) {
this.#emitter.destroy();
return true;
}
return false;
@ -130,14 +133,6 @@ export default (latus) => class Emitter extends decorate(Trait) {
return hooks;
}
emitParticleJson(json, emitter) {
const {fromResourceType: {Entity}} = resource(latus);
Entity.loadOrInstance(json).then((particle) => {
this.entity.emitParticleEntity(particle);
emitter.emit(particle);
});
}
listeners() {
return {
@ -189,18 +184,18 @@ export default (latus) => class Emitter extends decorate(Trait) {
particle.scale.end,
),
];
const protonParticle = this.emitter.createParticle(
const protonParticle = this.#emitter.createParticle(
initializers,
behaviors,
);
entity.on('destroy', () => {
this.emitter.removeParticle(protonParticle);
this.#emitter.removeParticle(protonParticle);
});
if (particle.listed) {
this.entity.list.addEntity(entity);
}
// Prime.
this.onParticleUpdate(protonParticle);
this.#onParticleUpdate(protonParticle);
return entity;
},
@ -222,9 +217,9 @@ export default (latus) => class Emitter extends decorate(Trait) {
count -= 1;
if (count > 0) {
const removeEmission = () => {
const index = this.emissions.indexOf(ticker);
const index = this.#emissions.indexOf(ticker);
if (-1 !== index) {
this.emissions.splice(index, 1);
this.#emissions.splice(index, 1);
}
emitter.end();
};
@ -235,7 +230,7 @@ export default (latus) => class Emitter extends decorate(Trait) {
removeEmission();
}
});
this.emissions.push(ticker);
this.#emissions.push(ticker);
return;
}
}
@ -247,7 +242,7 @@ export default (latus) => class Emitter extends decorate(Trait) {
},
emitParticle: (key, json = {}) => {
const particleJson = this.particles[key];
const particleJson = this.#particles[key];
if (!particleJson) {
return undefined;
}
@ -258,10 +253,27 @@ export default (latus) => class Emitter extends decorate(Trait) {
};
}
// eslint-disable-next-line class-methods-use-this
onParticleDead(particle) {
if (particle.body.isTransientParticle) {
particle.body.destroy();
}
}
// eslint-disable-next-line class-methods-use-this
onParticleUpdate(particle) {
particle.body.setPosition([particle.p.x, particle.p.y]);
/* eslint-disable no-param-reassign */
particle.body.opacity = particle.alpha;
particle.body.visibleScale = [particle.scale, particle.scale];
particle.body.rotation = particle.rotation * PI_180;
/* eslint-enable no-param-reassign */
}
tick(elapsed) {
this.emitter.update(elapsed);
for (let i = 0; i < this.emissions.length; i++) {
this.emissions[i].tick(elapsed);
this.#emitter.update(elapsed);
for (let i = 0; i < this.#emissions.length; i++) {
this.#emissions[i].tick(elapsed);
}
}

View File

@ -13,6 +13,33 @@ const decorate = compose(
export default class Physical extends decorate(Trait) {
constructor(entity, params, state) {
super(entity, params, state);
this._body = undefined;
this.bodyView = undefined;
this._world = undefined;
}
addToWorld() {
const world = this._world;
if (world) {
const body = world.createBody(this.entity.shape);
world.associateBodyWithEntity(body, this.entity);
body.setCollisionForEntity(this.entity);
world.addBody(body);
this._body = body;
if (AVOCADO_CLIENT) {
if (this.entity.is('visible') && this.entity.is('debuggable')) {
this.bodyView = new BodyView(body);
this.bodyView.position = Vector.scale(this.entity.position, -1);
this.bodyView.visible = this.entity.isDebugging;
this.bodyView.zIndex = 101;
this.entity.container.addChild(this.bodyView);
}
}
}
}
static behaviorTypes() {
return {
applyForce: {
@ -36,6 +63,10 @@ export default class Physical extends decorate(Trait) {
};
}
get body() {
return this._body;
}
static defaultState() {
return {
addedToPhysics: true,
@ -51,61 +82,10 @@ export default class Physical extends decorate(Trait) {
};
}
constructor(entity, params, state) {
super(entity, params, state);
this._body = undefined;
this.bodyView = undefined;
this._world = undefined;
}
destroy() {
this.world = undefined;
}
addToWorld() {
const world = this._world;
if (world) {
const body = world.createBody(this.entity.shape);
world.associateBodyWithEntity(body, this.entity);
body.setCollisionForEntity(this.entity);
world.addBody(body);
this._body = body;
if (AVOCADO_CLIENT) {
if (this.entity.is('visible') && this.entity.is('debuggable')) {
this.bodyView = new BodyView(body);
this.bodyView.position = Vector.scale(this.entity.position, -1);
this.bodyView.visible = this.entity.isDebugging;
this.bodyView.zIndex = 101;
this.entity.container.addChild(this.bodyView);
}
}
}
}
get body() {
return this._body;
}
removeFromWorld() {
if (this._world && this._body) {
this._world.removeBody(this._body);
}
this._body = undefined;
if (this.bodyView) {
if (this.entity.is('visible')) {
this.entity.container.removeChild(this.bodyView);
}
this.bodyView.destroy();
}
this.bodyView = undefined;
}
set world(world) {
this.removeFromWorld();
this._world = world;
this.addToWorld();
}
listeners() {
return {
@ -162,4 +142,24 @@ export default class Physical extends decorate(Trait) {
};
}
removeFromWorld() {
if (this._world && this._body) {
this._world.removeBody(this._body);
}
this._body = undefined;
if (this.bodyView) {
if (this.entity.is('visible')) {
this.entity.container.removeChild(this.bodyView);
}
this.bodyView.destroy();
}
this.bodyView = undefined;
}
set world(world) {
this.removeFromWorld();
this._world = world;
this.addToWorld();
}
}

View File

@ -9,6 +9,16 @@ const decorate = compose(
export default class Shaped extends decorate(Trait) {
#shape;
#shapeView;
constructor(...args) {
super(...args);
this.#shape = shapeFromJSON(this.params.shape);
this.#shapeView = undefined;
}
static defaultParams() {
return {
shape: undefined,
@ -24,35 +34,25 @@ export default class Shaped extends decorate(Trait) {
};
}
constructor(entity, params, state) {
super(entity, params, state);
this._shape = shapeFromJSON(this.params.shape);
this.shapeView = undefined;
}
destroy() {
this._shape.destroy();
if (this.shapeView) {
this.shapeView.destroy();
this.shapeView = undefined;
this.#shape.destroy();
if (this.#shapeView) {
this.#shapeView.destroy();
this.#shapeView = undefined;
}
}
get shape() {
return this._shape;
}
listeners() {
return {
traitAdded: () => {
if (AVOCADO_CLIENT) {
if (this.entity.is('visible') && this.entity.is('debuggable')) {
if (!this.shapeView) {
this.shapeView = new ShapeView(this.entity.shape);
this.shapeView.visible = this.entity.isDebugging;
this.shapeView.zIndex = 100;
this.entity.container.addChild(this.shapeView);
if (!this.#shapeView) {
this.#shapeView = new ShapeView(this.entity.shape);
this.#shapeView.visible = this.entity.isDebugging;
this.#shapeView.zIndex = 100;
this.entity.container.addChild(this.#shapeView);
}
}
}
@ -61,4 +61,8 @@ export default class Shaped extends decorate(Trait) {
};
}
get shape() {
return this.#shape;
}
}