refactor: particle physics

This commit is contained in:
cha0s 2019-11-03 10:43:05 -06:00
parent 308131449d
commit aaba818802
2 changed files with 83 additions and 160 deletions

View File

@ -1,102 +0,0 @@
import {Proton, TextNode} from '@avocado/graphics';
class DamageTextNode extends TextNode {
constructor(damage) {
const {amount} = damage;
super(amount);
this.damage = damage;
}
sizeInPx() {
const {amount} = this.damage;
// Big numbers are literally big.
if (amount > 999) {
return 12;
}
else if (amount > 99) {
return 10;
}
else if (amount > 9) {
return 8;
}
else {
return 6;
}
}
spanClassName() {
const {damageSpec, isDamage} = this.damage;
let className = super.spanClassName();
className += ' affinity-' + damageSpec.affinity;
if (isDamage) {
className += ' is-damage';
}
else {
className += ' is-healing';
}
return className;
}
}
export class DamageEmitter {
constructor() {
const proton = new Proton();
const emitter = new Proton.Emitter();
proton.addEmitter(emitter);
this.emitter = emitter;
this.proton = proton;
}
addRenderer(renderer) {
this.renderer = renderer;
this.proton.addRender(this.renderer);
}
destroy() {
this.proton.destroy();
}
emit(position, damage) {
// BUGS
const pz = new Proton.PointZone();
pz.x = position[0];
pz.y = -position[1];
const initializers = [
new Proton.Body(new DamageTextNode(damage)),
new Proton.Position(pz),
new Proton.Mass(1),
new Proton.Life(2),
new Proton.Velocity(
new Proton.Span(50, 90),
new Proton.Vector3D(0, 5, 0),
27.5
),
];
// Heh, bugs.
const rot = new Proton.Rotate(0, 0, 0);
rot.a = new Proton.Span(-.006, .006);
const behaviors = [
new Proton.Alpha(1, .25),
new Proton.Scale(.8, 1.2),
new Proton.Force(0, -0.5, 0),
rot,
];
this.emitter.createParticle(initializers, behaviors);
}
hasParticles() {
return this.particleCount > 0;
}
get particleCount() {
return this.emitter.particles.length;
}
tick(elapsed) {
this.proton.tick(elapsed);
}
}

View File

@ -1,5 +1,3 @@
import * as I from 'immutable';
import {Trait} from '@avocado/entity';
import {
behaviorItemFromJSON,
@ -8,16 +6,14 @@ import {
Context,
} from '@avocado/behavior';
import {hasGraphics, TextNodeRenderer} from '@avocado/graphics';
import {Vector} from '@avocado/math';
import {randomNumber, Vector} from '@avocado/math';
import {DamagePacket} from './damage.packet';
import {DamageEmitter} from './emitter';
export class Vulnerable extends Trait {
static defaultParams() {
const emitDamage = buildInvoke(['entity', 'emitParticle'], [
'damage',
const emitDamage = buildInvoke(['entity', 'emitDamageParticle'], [
buildTraversal(['entity', 'position']),
buildTraversal(['damage']),
]);
@ -45,9 +41,6 @@ export class Vulnerable extends Trait {
this.damageId = 0;
this.damageTickingPromises = [];
this.damages = [];
this._hasAddedEmitter = false;
this._hasAddedEmitterRenderer = false;
this._isHydrating = false;
this._isInvulnerable = false;
this.locks = new Map();
this._tookDamageActions = behaviorItemFromJSON(
@ -60,14 +53,6 @@ export class Vulnerable extends Trait {
this.damageTickingPromises = [];
}
hydrate() {
if (AVOCADO_CLIENT) {
this._isHydrating = true;
this.addEmitter();
this.addEmitterRenderer();
}
}
acceptDamage(damage) {
const context = new Context({
damage,
@ -95,42 +80,28 @@ export class Vulnerable extends Trait {
}
}
addEmitter() {
if (!this._isHydrating) {
return;
}
if (this._hasAddedEmitter) {
return;
}
if (!this.entity.is('emitter')) {
return;
}
this.entity.addEmitter('damage', new DamageEmitter());
this._hasAddedEmitter = true;
}
addEmitterRenderer() {
if (!this._isHydrating) {
return;
}
if (this._hasAddedEmitterRenderer) {
return;
}
if (!this.entity.is('emitter')) {
return;
}
if (!this.entity.is('staged') || !this.entity.stage) {
return;
}
const renderer = new TextNodeRenderer('.damage', this.entity.stage);
this.entity.addEmitterRenderer('damage', renderer);
this._hasAddedEmitterRenderer = true;
}
cleanPackets() {
this.damages = [];
}
damageTextSize(amount) {
const biggest = 16;
const smallest = biggest / 2;
const step = biggest / 6;
if (amount > 999) {
return biggest;
}
else if (amount > 99) {
return smallest + (step * 2);
}
else if (amount > 9) {
return smallest + step;
}
else {
return smallest;
}
}
get isInvulnerable() {
return this._isInvulnerable;
}
@ -152,10 +123,6 @@ export class Vulnerable extends Trait {
this._isInvulnerable = isDying;
},
stageChanged: () => {
this.addEmitterRenderer();
},
tookDamage: (damage) => {
if (AVOCADO_SERVER) {
this.damages.push(damage);
@ -163,17 +130,75 @@ export class Vulnerable extends Trait {
}
},
traitsChanged: () => {
this.addEmitter();
this.addEmitterRenderer();
},
};
}
methods() {
return {
emitDamageParticle: (position, damage) => {
const {amount, damageSpec, isDamage} = damage;
const fill = isDamage ? '#FF0000' : '#00FF77';
this.entity.emitParticleJson({
traits: {
darkened: {
params: {
isDarkened: false,
},
},
emitted: {
params: {
alpha: {
start: 1,
end: 0,
},
force: [0, 1],
velocity: [
randomNumber(-0.5, 0.5),
randomNumber(-1.25, -0.75)
],
position,
rotation: {
start: 0,
add: {
min: -0.5,
max: 0.5,
},
},
scale: {
start: 1,
end: 1.25,
},
},
},
existent: {},
layered: {},
listed: {},
positioned: {},
roomed: {},
textual: {
state: {
text: amount,
textStyle: {
fill,
fontFamily: 'joystix',
fontSize: this.damageTextSize(amount),
strokeThickness: 2,
},
},
},
visible: {
state: {
zIndex: 65535,
}
},
},
}).then((particle) => {
this.entity.list.addEntity(particle);
});
},
takeDamageFrom: (entity) => {
const damageSpecs = entity.damageSpecs;
for (let i = 0; i < damageSpecs.length; ++i) {