feat: vulnerable, damaging, some fire :)

This commit is contained in:
cha0s 2019-04-19 02:54:59 -05:00
parent 35f6e3ab4a
commit d39ca16624
7 changed files with 308 additions and 4 deletions

View File

@ -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);
}
}
}
}

71
common/damage/emitter.js Normal file
View File

@ -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';
}
}
}

View File

@ -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);
}
}
}
}

BIN
resource/fire.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

View File

@ -47,6 +47,7 @@ export function createEntityForConnection(socket) {
},
},
},
vulnerable: {},
},
});
entity.addTrait('controllable');

View File

@ -1,5 +1,52 @@
import {World} from '@avocado/physics/matter/world';
import {Room} from '@avocado/topdown';
// A fire.
function fireJSON(position) {
return {
traits: {
collider: {
params: {
isSensor: true,
},
},
damaging: {
params: {
power: 70,
affinities: ['fire'],
},
},
existent: {},
visible: {},
physical: {},
pictured: {
params: {
images: {
initial: {
offset: [0, 0],
size: [16, 16], // Derive?
uri: '/fire.png',
},
}
},
},
positioned: {
state: {
x: position[0],
y: position[1],
},
},
shaped: {
params: {
shape: {
type: 'rectangle',
position: [0, 0],
size: [16, 16],
},
},
},
},
};
}
// A flower barrel.
function flowerBarrelJSON(position) {
return {
@ -201,6 +248,7 @@ function kittyJSON(position) {
},
},
},
vulnerable: {},
},
};
}
@ -243,6 +291,7 @@ const roomJSON = {
},
},
};
roomJSON.layers.everything.entities.push(fireJSON([200, 200]));
for (let i = 0; i < 4; ++i) {
const x = Math.floor(Math.random() * 284) + 50;
const y = Math.floor(Math.random() * 284) + 50;

View File

@ -37,8 +37,8 @@
lodash.without "4.4.0"
"@avocado/graphics@1.x":
version "1.0.1"
resolved "https://npm.i12e.cha0s.io/@avocado%2fgraphics/-/graphics-1.0.1.tgz#ce799e134425d9c5d117aafafd35d5f52d2defda"
version "1.0.2"
resolved "https://npm.i12e.cha0s.io/@avocado%2fgraphics/-/graphics-1.0.2.tgz#a424f69b0f0c12476ff58229e92c5f6dabc15506"
dependencies:
"@avocado/core" "1.x"
"@avocado/math" "1.x"
@ -47,6 +47,8 @@
debug "^3.1.0"
immutable "4.0.0-rc.12"
pixi.js "4.8.6"
three "0.103.0"
three.proton.js "0.1.5"
"@avocado/input@1.x":
version "1.0.1"
@ -3889,8 +3891,8 @@ resolve@^1.3.2:
path-parse "^1.0.6"
resource-loader@^2.2.3:
version "2.2.3"
resolved "https://npm.i12e.cha0s.io/resource-loader/-/resource-loader-2.2.3.tgz#2c8b075b7b9328a2e72fba6f51b4dff274870000"
version "2.2.4"
resolved "https://npm.i12e.cha0s.io/resource-loader/-/resource-loader-2.2.4.tgz#9bf43dba59475d56be29c796399211ce0e96fd2d"
dependencies:
mini-signals "^1.1.1"
parse-uri "^1.0.0"
@ -4367,6 +4369,14 @@ terser@^3.16.1:
source-map "~0.6.1"
source-map-support "~0.5.10"
three.proton.js@0.1.5:
version "0.1.5"
resolved "https://npm.i12e.cha0s.io/three.proton.js/-/three.proton.js-0.1.5.tgz#3ae32fd9cf3b5698e3b546946e53badbda04948e"
three@0.103.0:
version "0.103.0"
resolved "https://npm.i12e.cha0s.io/three/-/three-0.103.0.tgz#63b3dbccc861caad93269618061a73dadebae71b"
through2@^2.0.0:
version "2.0.5"
resolved "https://npm.i12e.cha0s.io/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"