flow: hoe!

This commit is contained in:
cha0s 2019-05-27 17:30:40 -05:00
parent 9e9ad39685
commit 41c271752e
7 changed files with 230 additions and 1 deletions

View File

@ -357,6 +357,17 @@ export class App extends decorate(class {}) {
this.stage.camera = camera;
// Avoid the initial 'lerp.
camera.realPosition = camera.position;
// Manage held item.
entity.on('activeSlotIndexChanged', (oldIndex, newIndex) => {
const oldItem = entity.itemInSlot(oldIndex);
if (oldItem) {
oldItem.wielder = null;
}
const newItem = entity.itemInSlot(newIndex);
if (newItem) {
newItem.wielder = entity;
}
});
}
}
}

View File

@ -1,9 +1,15 @@
import {behaviorItemFromJSON} from '@avocado/behavior';
import {compose, TickingPromise} from '@avocado/core';
import {compose, Property, TickingPromise} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
import {Image} from '@avocado/graphics';
const decorate = compose(
Property('wielder', {
track: true,
emit: function (...args) {
this.entity.emit(...args);
},
}),
StateProperty('qty', {
track: true,
}),

181
common/traits/tool.trait.js Normal file
View File

@ -0,0 +1,181 @@
import {compose} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
import {Color, Primitives} from '@avocado/graphics';
import {Rectangle, Vector} from '@avocado/math';
const decorate = compose(
);
// Tools.
export class Tool extends decorate(Trait) {
static defaultParams() {
return {
target: {
type: 'projection',
distance: 1,
length: 1,
width: 1,
},
};
}
static type() {
return 'tool';
}
constructor(entity, params, state) {
super(entity, params, state);
if (AVOCADO_CLIENT) {
this.guidePrimitives = new Primitives();
}
if (1 !== this.params.target.length % 2) {
throw new Error("Tool::params.target.length must be odd!");
}
if (1 !== this.params.target.width % 2) {
throw new Error("Tool::params.target.width must be odd!");
}
this.targets = [];
}
calculateTargetStart() {
const wielder = this.entity.wielder;
if (!wielder) {
return;
}
if (!wielder.is('directional')) {
return;
}
if (!wielder.is('layered')) {
return;
}
const tile = Vector.floor(wielder.tile);
const distance = this.params.target.distance;
return Vector.add(
tile,
Vector.directionalProjection(wielder.direction, [0, distance]),
);
}
calculateTargets() {
this.targets = [];
const wielder = this.entity.wielder;
if (!wielder) {
return;
}
if (!wielder.is('layered')) {
return;
}
const layer = wielder.layer;
if (!layer) {
return;
}
const tile = Vector.floor(wielder.tile);
const tileset = layer.tileset;
if (!tileset) {
return;
}
if (!wielder.is('directional')) {
return;
}
const direction = wielder.direction;
const start = this.calculateTargetStart();
const width = (this.params.target.width - 1) / 2;
for (let i = -width; i < (width + 1); ++i) {
for (let j = 0; j < this.params.target.length; ++j) {
this.targets.push(Vector.add(
start,
Vector.directionalProjection(direction, [i, j]),
));
}
}
}
onWielderDirectionChanged() {
this.calculateTargets();
this.renderPrimitives();
}
onWielderPositionChanged() {
this.repositionPrimitives();
}
renderPrimitives() {
this.guidePrimitives.clear();
const wielder = this.entity.wielder;
if (!wielder) {
return;
}
if (!wielder.is('layered')) {
return;
}
const layer = wielder.layer;
if (!layer) {
return;
}
const tile = Vector.floor(wielder.tile);
const tileset = layer.tileset;
if (!tileset) {
return;
}
const tileSize = tileset.tileSize;
for (let i = 0; i < this.targets.length; ++i) {
const target = this.targets[i];
const relativeTarget = Vector.sub(target, tile);
const scaledRelativeTarget = Vector.mul(relativeTarget, tileSize);
this.guidePrimitives.drawRectangle(
Rectangle.compose(scaledRelativeTarget, tileSize),
Primitives.lineStyle(new Color(255, 255, 255), 1),
);
}
}
repositionPrimitives() {
const wielder = this.entity.wielder;
if (!wielder) {
return;
}
if (!wielder.is('layered')) {
return;
}
this.guidePrimitives.position = Vector.scale(wielder.tileOffset, -1);
}
listeners() {
return {
wielderChanged: (oldWielder, newWielder) => {
if (oldWielder && oldWielder.is('visible')) {
oldWielder.off(
'positionChanged',
this.onWielderPositionChanged,
);
oldWielder.off(
'directionChanged',
this.onWielderDirectionChanged,
);
oldWielder.container.removeChild(this.guidePrimitives);
}
if (newWielder && newWielder.is('visible')) {
newWielder.on(
'positionChanged',
this.onWielderPositionChanged,
this,
);
newWielder.on(
'directionChanged',
this.onWielderDirectionChanged,
this,
);
newWielder.container.addChild(this.guidePrimitives);
}
this.calculateTargets();
this.renderPrimitives();
this.repositionPrimitives();
},
};
}
}

BIN
resource/hoe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

View File

@ -70,6 +70,10 @@ export function createEntityForConnection(socket) {
qty: 1,
uri: '/rock.entity.json',
},
2: {
qty: 1,
uri: '/hoe.entity.json',
},
},
},
},

View File

@ -30,6 +30,8 @@ import {potionJSON} from './fixtures/potion.entity';
writeFixture('potion.entity.json', potionJSON());
import {rockJSON} from './fixtures/rock.entity';
writeFixture('rock.entity.json', rockJSON());
import {hoeJSON} from './fixtures/hoe.entity';
writeFixture('hoe.entity.json', hoeJSON());
// Write rooms.
import {kittyFireJSON} from './fixtures/kitty-fire.room';
writeFixture('kitty-fire.room.json', kittyFireJSON());

View File

@ -0,0 +1,25 @@
// Hoe.
export function hoeJSON() {
return {
traits: {
existent: {},
item: {
params: {
slotImages: {
default: '/hoe.png',
},
},
},
tool: {
params: {
target: {
type: 'projection',
distance: 1,
length: 3,
width: 1,
},
},
},
},
};
}