feat: vulnerable, damaging, some fire :)
This commit is contained in:
parent
35f6e3ab4a
commit
d39ca16624
65
common/damage/damaging.trait.js
Normal file
65
common/damage/damaging.trait.js
Normal 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
71
common/damage/emitter.js
Normal 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';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
108
common/damage/vulnerable.trait.js
Normal file
108
common/damage/vulnerable.trait.js
Normal 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
BIN
resource/fire.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 160 B |
|
@ -47,6 +47,7 @@ export function createEntityForConnection(socket) {
|
|||
},
|
||||
},
|
||||
},
|
||||
vulnerable: {},
|
||||
},
|
||||
});
|
||||
entity.addTrait('controllable');
|
||||
|
|
|
@ -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;
|
||||
|
|
18
yarn.lock
18
yarn.lock
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue
Block a user