From d39ca166249a18df193d7d14dee510d1ec5290f7 Mon Sep 17 00:00:00 2001 From: cha0s Date: Fri, 19 Apr 2019 02:54:59 -0500 Subject: [PATCH] feat: vulnerable, damaging, some fire :) --- common/damage/damaging.trait.js | 65 +++++++++++++++ common/damage/emitter.js | 71 ++++++++++++++++ common/damage/vulnerable.trait.js | 108 +++++++++++++++++++++++++ resource/fire.png | Bin 0 -> 160 bytes server/create-entity-for-connection.js | 1 + server/create-server-room.js | 49 +++++++++++ yarn.lock | 18 ++++- 7 files changed, 308 insertions(+), 4 deletions(-) create mode 100644 common/damage/damaging.trait.js create mode 100644 common/damage/emitter.js create mode 100644 common/damage/vulnerable.trait.js create mode 100644 resource/fire.png diff --git a/common/damage/damaging.trait.js b/common/damage/damaging.trait.js new file mode 100644 index 0000000..6991adc --- /dev/null +++ b/common/damage/damaging.trait.js @@ -0,0 +1,65 @@ +import * as I from 'immutable'; + +import {Trait} from '@avocado/entity'; + +export class Damaging extends Trait { + + static defaultParams() { + return { + affinities: [], + lock: 0.1, + power: 0, + variance: 0.2, + }; + } + + initialize() { + this._affinities = this.params.get('affinities').toJS(); + this._collidingWith = []; + this._lock = this.params.get('lock'); + this._power = this.params.get('power'); + this._variance = this.params.get('variance'); + } + + get affinities() { + return this._affinities; + } + + get lock() { + return this._lock; + } + + get power() { + return this._power; + } + + get variance() { + return this._variance; + } + + listeners() { + return { + + collisionEnd: (other) => { + const index = this._collidingWith.indexOf(other); + this._collidingWith.splice(index, 1); + }, + + collisionStart: (other) => { + this._collidingWith.push(other); + }, + + }; + } + + tick(elapsed) { + for (let i = 0; i < this._collidingWith.length; ++i) { + const entity = this._collidingWith[i]; + if (entity.is('vulnerable')) { + entity.takeDamageFrom(this.entity); + } + } + } + +} + diff --git a/common/damage/emitter.js b/common/damage/emitter.js new file mode 100644 index 0000000..b4efbe3 --- /dev/null +++ b/common/damage/emitter.js @@ -0,0 +1,71 @@ +import {Proton, TextNode, TextNodeRenderer} from '@avocado/graphics'; + +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); + } + + emit(position, amount) { + // BUGS + const pz = new Proton.PointZone(); + pz.x = position[0]; + pz.y = -position[1]; + const initializers = [ + new Proton.Body(new DamageTextNode(Math.abs(amount))), + new Proton.Position(pz), + new Proton.Mass(1), + new Proton.Life(2), + new Proton.Velocity( + new Proton.Span(80, 120), + new Proton.Vector3D(0, 5, 0), + 27.5 + ), + ]; + // Heh, bugs. + const rot = new Proton.Rotate(0, 0, 0); + rot.a = new Proton.Span(-.003, .003); + const behaviors = [ + new Proton.Alpha(1, .5), + new Proton.Color(amount < 0 ? 0x00ff00 : 0xff0000), + new Proton.Scale(.6, 1), + new Proton.Force(0, -1, 0), + rot, + ]; + this.emitter.createParticle(initializers, behaviors); + } + + tick(elapsed) { + this.proton.tick(elapsed); + } + +} + +export class DamageTextNode extends TextNode { + + constructor(damage) { + super(damage); + if (damage > 999) { + this.span.style.fontSize = '2em'; + } + else if (damage > 99) { + this.span.style.fontSize = '1.5em'; + } + else if (damage > 9) { + this.span.style.fontSize = '1.2em'; + } + else { + this.span.style.fontSize = '1em'; + } + } + +} diff --git a/common/damage/vulnerable.trait.js b/common/damage/vulnerable.trait.js new file mode 100644 index 0000000..567f0a2 --- /dev/null +++ b/common/damage/vulnerable.trait.js @@ -0,0 +1,108 @@ +import * as I from 'immutable'; + +import {Trait} from '@avocado/entity'; +import {hasGraphics, TextNodeRenderer} from '@avocado/graphics'; + +import {DamageEmitter} from './emitter'; + +export class Vulnerable extends Trait { + + static defaultState() { + return { + damageList: I.Map(), + }; + } + + initialize() { + this.damageList = {}; + this.locks = new Map(); + if (hasGraphics) { + this.emitter = new DamageEmitter(); + this.setRenderer(); + } + } + + patchStateStep(key, step) { + if ('state' !== key) { + return; + } + const stateKey = step.path.substr(1); + const value = this.transformPatchValue(stateKey, step.value); + const stateKeyParts = stateKey.split('/'); + switch (stateKeyParts[0]) { + case 'damageList': + for (let i = 0; i < value.length; ++i) { + const amount = value[i]; + this.emitter.emit(this.entity.position, amount); + } + break; + default: + super.patchStateStep(key, step); + break; + } + } + + setRenderer() { + if (this.entity.is('staged') && this.entity.stage) { + const renderer = new TextNodeRenderer('.damage', this.entity.stage); + this.emitter.addRenderer(renderer); + } + } + + listeners() { + return { + + stageChanged: () => { + this.setRenderer(); + }, + + }; + } + + methods() { + return { + + takeDamageFrom: (entity) => { + if (this.locks.has(entity)) { + return; + } + this.locks.set(entity, entity.lock); + const variance = Math.random() * entity.variance * 2 - entity.variance; + const difference = entity.power * variance; + const amount = (entity.power + difference) >> 0; + if (!this.damageList[entity.instanceUuid]) { + this.damageList[entity.instanceUuid] = []; + } + this.damageList[entity.instanceUuid].push(amount); + }, + + }; + } + + tick(elapsed) { + if (this.state.get('damageList').size > 0) { + this.state = this.state.set('damageList', I.Map()); + } + if (Object.keys(this.damageList).length > 0) { + this.state = this.state.set('damageList', I.Map(this.damageList)); + this.isDirty = true; + this.damageList = {}; + } + if (hasGraphics) { + this.emitter.tick(elapsed); + } + const keys = Array.from(this.locks.keys()); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const remaining = this.locks.get(key) - elapsed; + if (remaining <= 0) { + this.locks.delete(key); + } + else { + this.locks.set(key, remaining); + } + } + } + +} + diff --git a/resource/fire.png b/resource/fire.png new file mode 100644 index 0000000000000000000000000000000000000000..fa12008cc3f672735057f035b78507e077d59919 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#F^e!eyIJ0xj%Pq2$r9Iy66gHf+|;}h2Ir#G#FEq$h4Rdj3KvfK$u6{1-oD!M