Compare commits
6 Commits
af541f1b7e
...
56e5db6898
Author | SHA1 | Date | |
---|---|---|---|
|
56e5db6898 | ||
|
702650e04e | ||
|
309c94bbfc | ||
|
ac12fafa16 | ||
|
694cd90645 | ||
|
220acccc08 |
|
@ -1,13 +1,43 @@
|
||||||
|
import {isSpreadElement} from '@/astride/types.js';
|
||||||
|
|
||||||
export default function(node, {evaluate, scope}) {
|
export default function(node, {evaluate, scope}) {
|
||||||
const elements = [];
|
const elements = [];
|
||||||
|
const asyncSpread = Object.create(null);
|
||||||
let isAsync = false;
|
let isAsync = false;
|
||||||
for (const element of node.elements) {
|
for (const index in node.elements) {
|
||||||
const {async, value} = evaluate(element, {scope});
|
const element = node.elements[index];
|
||||||
isAsync = isAsync || async;
|
if (isSpreadElement(element)) {
|
||||||
elements.push(value);
|
const {async, value} = evaluate(element.argument, {scope});
|
||||||
|
isAsync = isAsync || async;
|
||||||
|
if (async) {
|
||||||
|
elements.push(value);
|
||||||
|
asyncSpread[elements.length - 1] = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elements.push(...value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const {async, value} = evaluate(element, {scope});
|
||||||
|
isAsync = isAsync || async;
|
||||||
|
elements.push(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
async: !!isAsync,
|
async: !!isAsync,
|
||||||
value: isAsync ? Promise.all(elements) : elements,
|
value: !isAsync
|
||||||
|
? elements
|
||||||
|
: Promise.all(elements).then((elementsAndOrSpreads) => {
|
||||||
|
const elements = [];
|
||||||
|
for (let i = 0; i < elementsAndOrSpreads.length; ++i) {
|
||||||
|
if (asyncSpread[i]) {
|
||||||
|
elements.push(...elementsAndOrSpreads[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elements.push(elementsAndOrSpreads[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elements;
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,19 @@ import expression from '@/astride/test/expression.js';
|
||||||
test('evaluates array of literals', async () => {
|
test('evaluates array of literals', async () => {
|
||||||
expect(evaluate(await expression('[1.5, 2, "three"]')))
|
expect(evaluate(await expression('[1.5, 2, "three"]')))
|
||||||
.to.deep.include({value: [1.5, 2, 'three']});
|
.to.deep.include({value: [1.5, 2, 'three']});
|
||||||
});
|
|
||||||
|
|
||||||
test('evaluates array containing promises', async () => {
|
|
||||||
const evaluated = evaluate(await expression('[1.5, 2, await "three"]'));
|
const evaluated = evaluate(await expression('[1.5, 2, await "three"]'));
|
||||||
expect(evaluated.async)
|
expect(evaluated.async)
|
||||||
.to.equal(true);
|
.to.equal(true);
|
||||||
expect(await evaluated.value)
|
expect(await evaluated.value)
|
||||||
.to.deep.equal([1.5, 2, 'three']);
|
.to.deep.equal([1.5, 2, 'three']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('evaluates array spread', async () => {
|
||||||
|
expect(evaluate(await expression('[...[4, 5, 6], 1.5, 2, "three"]')))
|
||||||
|
.to.deep.include({value: [4, 5, 6, 1.5, 2, 'three']});
|
||||||
|
const evaluated = evaluate(await expression('[...(await [4, 5, 6]), 1.5, 2, await "three"]'));
|
||||||
|
expect(evaluated.async)
|
||||||
|
.to.equal(true);
|
||||||
|
expect(await evaluated.value)
|
||||||
|
.to.deep.equal([4, 5, 6, 1.5, 2, 'three']);
|
||||||
|
});
|
||||||
|
|
31
app/ecs-components/emitter.js
Normal file
31
app/ecs-components/emitter.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import Schema from '@/ecs/schema.js';
|
||||||
|
|
||||||
|
export default function(Component) {
|
||||||
|
return class Emitter extends Component {
|
||||||
|
mergeDiff(original, update) {
|
||||||
|
const merged = {};
|
||||||
|
if (update.emit) {
|
||||||
|
merged.emit = {
|
||||||
|
...original.emit,
|
||||||
|
...update.emit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
instanceFromSchema() {
|
||||||
|
const Component = this;
|
||||||
|
const Instance = super.instanceFromSchema();
|
||||||
|
return class EmitterInstance extends Instance {
|
||||||
|
emitting = [];
|
||||||
|
id = 0;
|
||||||
|
emit(specification) {
|
||||||
|
Component.markChange(this.entity, 'emit', {[this.id++]: specification});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static schema = new Schema({
|
||||||
|
type: 'object',
|
||||||
|
properties: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
29
app/ecs-components/sound.js
Normal file
29
app/ecs-components/sound.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import Schema from '@/ecs/schema.js';
|
||||||
|
|
||||||
|
export default function(Component) {
|
||||||
|
return class Sound extends Component {
|
||||||
|
mergeDiff(original, update) {
|
||||||
|
const merged = {};
|
||||||
|
if (update.play) {
|
||||||
|
merged.play = [
|
||||||
|
...(original.play ?? []),
|
||||||
|
...update.play,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
instanceFromSchema() {
|
||||||
|
const Component = this;
|
||||||
|
const Instance = super.instanceFromSchema();
|
||||||
|
return class SoundInstance extends Instance {
|
||||||
|
play(source) {
|
||||||
|
Component.markChange(this.entity, 'play', [source]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static schema = new Schema({
|
||||||
|
type: 'object',
|
||||||
|
properties: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,6 +48,12 @@ export default function(Component) {
|
||||||
constructor(layer) {
|
constructor(layer) {
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
}
|
}
|
||||||
|
get area() {
|
||||||
|
return this.layer.area;
|
||||||
|
}
|
||||||
|
get source() {
|
||||||
|
return this.layer.source;
|
||||||
|
}
|
||||||
stamp(at, data) {
|
stamp(at, data) {
|
||||||
const changes = {};
|
const changes = {};
|
||||||
for (const row in data) {
|
for (const row in data) {
|
||||||
|
@ -72,6 +78,9 @@ export default function(Component) {
|
||||||
}
|
}
|
||||||
return this.layer.data[y * this.layer.area.x + x];
|
return this.layer.data[y * this.layer.area.x + x];
|
||||||
}
|
}
|
||||||
|
get tileSize() {
|
||||||
|
return this.layer.tileSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new LayerProxy(layers[index]);
|
return new LayerProxy(layers[index]);
|
||||||
};
|
};
|
||||||
|
|
120
app/engine.js
120
app/engine.js
|
@ -45,6 +45,61 @@ export default class Engine {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acceptActions() {
|
||||||
|
for (const [
|
||||||
|
entity,
|
||||||
|
payload,
|
||||||
|
] of this.incomingActions) {
|
||||||
|
const {Controlled, Inventory, Ticking, Wielder} = entity;
|
||||||
|
switch (payload.type) {
|
||||||
|
case 'changeSlot': {
|
||||||
|
if (!Controlled.locked) {
|
||||||
|
Wielder.activeSlot = payload.value - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'moveUp':
|
||||||
|
case 'moveRight':
|
||||||
|
case 'moveDown':
|
||||||
|
case 'moveLeft': {
|
||||||
|
Controlled[payload.type] = payload.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'swapSlots': {
|
||||||
|
if (!Controlled.locked) {
|
||||||
|
Inventory.swapSlots(...payload.value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'use': {
|
||||||
|
if (!Controlled.locked) {
|
||||||
|
Inventory.item(Wielder.activeSlot + 1).then(async (item) => {
|
||||||
|
if (item) {
|
||||||
|
const code = await(
|
||||||
|
this.server.readAsset([
|
||||||
|
item.source,
|
||||||
|
payload.value ? 'start.js' : 'stop.js',
|
||||||
|
].join('/'))
|
||||||
|
.then((script) => (script.ok ? script.text() : ''))
|
||||||
|
);
|
||||||
|
if (code) {
|
||||||
|
const context = {
|
||||||
|
ecs: this.ecses[entity.Ecs.path],
|
||||||
|
item,
|
||||||
|
wielder: entity,
|
||||||
|
};
|
||||||
|
Ticking.addTickingPromise(Script.tickingPromise(code, context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.incomingActions = [];
|
||||||
|
}
|
||||||
|
|
||||||
async connectPlayer(connection, id) {
|
async connectPlayer(connection, id) {
|
||||||
const entityJson = await this.loadPlayer(id);
|
const entityJson = await this.loadPlayer(id);
|
||||||
if (!this.ecses[entityJson.Ecs.path]) {
|
if (!this.ecses[entityJson.Ecs.path]) {
|
||||||
|
@ -112,6 +167,7 @@ export default class Engine {
|
||||||
Controlled: {},
|
Controlled: {},
|
||||||
Direction: {direction: 2},
|
Direction: {direction: 2},
|
||||||
Ecs: {path: join('homesteads', `${id}`)},
|
Ecs: {path: join('homesteads', `${id}`)},
|
||||||
|
Emitter: {},
|
||||||
Forces: {},
|
Forces: {},
|
||||||
Inventory: {
|
Inventory: {
|
||||||
slots: {
|
slots: {
|
||||||
|
@ -133,6 +189,7 @@ export default class Engine {
|
||||||
Position: {x: 368, y: 368},
|
Position: {x: 368, y: 368},
|
||||||
VisibleAabb: {},
|
VisibleAabb: {},
|
||||||
Speed: {speed: 100},
|
Speed: {speed: 100},
|
||||||
|
Sound: {},
|
||||||
Sprite: {
|
Sprite: {
|
||||||
anchor: {x: 0.5, y: 0.8},
|
anchor: {x: 0.5, y: 0.8},
|
||||||
animation: 'moving:down',
|
animation: 'moving:down',
|
||||||
|
@ -208,12 +265,20 @@ export default class Engine {
|
||||||
await this.server.writeData(['players', `${id}`].join('/'), buffer);
|
await this.server.writeData(['players', `${id}`].join('/'), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setClean() {
|
||||||
|
for (const i in this.ecses) {
|
||||||
|
this.ecses[i].setClean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this.handle = setInterval(() => {
|
this.handle = setInterval(() => {
|
||||||
const elapsed = (Date.now() - this.last) / 1000;
|
const elapsed = (Date.now() - this.last) / 1000;
|
||||||
this.last = Date.now();
|
this.last = Date.now();
|
||||||
|
this.acceptActions();
|
||||||
this.tick(elapsed);
|
this.tick(elapsed);
|
||||||
this.update(elapsed);
|
this.update(elapsed);
|
||||||
|
this.setClean();
|
||||||
this.frame += 1;
|
this.frame += 1;
|
||||||
}, 1000 / TPS);
|
}, 1000 / TPS);
|
||||||
}
|
}
|
||||||
|
@ -224,61 +289,6 @@ export default class Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
for (const i in this.ecses) {
|
|
||||||
this.ecses[i].setClean();
|
|
||||||
}
|
|
||||||
for (const [
|
|
||||||
entity,
|
|
||||||
payload,
|
|
||||||
] of this.incomingActions) {
|
|
||||||
const {Controlled, Inventory, Ticking, Wielder} = entity;
|
|
||||||
switch (payload.type) {
|
|
||||||
case 'changeSlot': {
|
|
||||||
if (!Controlled.locked) {
|
|
||||||
Wielder.activeSlot = payload.value - 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'moveUp':
|
|
||||||
case 'moveRight':
|
|
||||||
case 'moveDown':
|
|
||||||
case 'moveLeft': {
|
|
||||||
Controlled[payload.type] = payload.value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'swapSlots': {
|
|
||||||
if (!Controlled.locked) {
|
|
||||||
Inventory.swapSlots(...payload.value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'use': {
|
|
||||||
if (!Controlled.locked) {
|
|
||||||
Inventory.item(Wielder.activeSlot + 1).then(async (item) => {
|
|
||||||
if (item) {
|
|
||||||
const code = await(
|
|
||||||
this.server.readAsset([
|
|
||||||
item.source,
|
|
||||||
payload.value ? 'start.js' : 'stop.js',
|
|
||||||
].join('/'))
|
|
||||||
.then((script) => (script.ok ? script.text() : ''))
|
|
||||||
);
|
|
||||||
if (code) {
|
|
||||||
const context = {
|
|
||||||
ecs: this.ecses[entity.Ecs.path],
|
|
||||||
item,
|
|
||||||
wielder: entity,
|
|
||||||
};
|
|
||||||
Ticking.addTickingPromise(Script.tickingPromise(code, context));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.incomingActions = [];
|
|
||||||
for (const i in this.ecses) {
|
for (const i in this.ecses) {
|
||||||
this.ecses[i].tick(elapsed);
|
this.ecses[i].tick(elapsed);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,11 +42,18 @@ export default function EcsComponent() {
|
||||||
}
|
}
|
||||||
const updatedEntities = {...entities};
|
const updatedEntities = {...entities};
|
||||||
for (const id in payload.ecs) {
|
for (const id in payload.ecs) {
|
||||||
if (false === payload.ecs[id]) {
|
const update = payload.ecs[id];
|
||||||
|
if (false === update) {
|
||||||
delete updatedEntities[id];
|
delete updatedEntities[id];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
updatedEntities[id] = ecs.get(id);
|
updatedEntities[id] = ecs.get(id);
|
||||||
|
if (update.Emitter?.emit) {
|
||||||
|
updatedEntities[id].Emitter.emitting = {
|
||||||
|
...updatedEntities[id].Emitter.emitting,
|
||||||
|
...update.Emitter.emit,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setEntities(updatedEntities);
|
setEntities(updatedEntities);
|
||||||
|
|
52
app/react-components/emitter.jsx
Normal file
52
app/react-components/emitter.jsx
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import {Container} from '@pixi/display';
|
||||||
|
import {PixiComponent} from '@pixi/react';
|
||||||
|
import * as particles from '@pixi/particle-emitter';
|
||||||
|
|
||||||
|
const EmitterInternal = PixiComponent('Emitter', {
|
||||||
|
$$emitter: undefined,
|
||||||
|
$$raf: undefined,
|
||||||
|
create() {
|
||||||
|
return new Container();
|
||||||
|
},
|
||||||
|
applyProps(container, oldProps, newProps) {
|
||||||
|
if (!this.$$emitter) {
|
||||||
|
const {onComplete, particle} = newProps;
|
||||||
|
this.$$emitter = new particles.Emitter(container, particle);
|
||||||
|
this.$$emitter._completeCallback = onComplete;
|
||||||
|
let last = Date.now();
|
||||||
|
const render = () => {
|
||||||
|
this.$$raf = requestAnimationFrame(render);
|
||||||
|
const now = Date.now();
|
||||||
|
this.$$emitter.update((now - last) / 1000);
|
||||||
|
last = now;
|
||||||
|
};
|
||||||
|
this.$$emitter.emit = true;
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
willUnmount() {
|
||||||
|
if (this.$$emitter) {
|
||||||
|
this.$$emitter.emit = false;
|
||||||
|
cancelAnimationFrame(this.$$raf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function Emitter({entity}) {
|
||||||
|
const {Emitter} = entity;
|
||||||
|
const emitters = [];
|
||||||
|
for (const id in Emitter.emitting) {
|
||||||
|
const particle = Emitter.emitting[id];
|
||||||
|
emitters.push(
|
||||||
|
<EmitterInternal
|
||||||
|
key={id}
|
||||||
|
onComplete={() => {
|
||||||
|
delete Emitter.emitting[id];
|
||||||
|
}}
|
||||||
|
particle={particle}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <>{emitters}</>;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {useCallback} from 'react';
|
||||||
|
|
||||||
import {useDebug} from '@/context/debug.js';
|
import {useDebug} from '@/context/debug.js';
|
||||||
|
|
||||||
|
import Emitter from './emitter.jsx';
|
||||||
import Sprite from './sprite.jsx';
|
import Sprite from './sprite.jsx';
|
||||||
|
|
||||||
function Crosshair({x, y}) {
|
function Crosshair({x, y}) {
|
||||||
|
@ -40,9 +41,16 @@ export default function Entities({entities}) {
|
||||||
<Container
|
<Container
|
||||||
key={id}
|
key={id}
|
||||||
>
|
>
|
||||||
<Sprite
|
{entity.Sprite && (
|
||||||
entity={entity}
|
<Sprite
|
||||||
/>
|
entity={entity}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{entity.Emitter && (
|
||||||
|
<Emitter
|
||||||
|
entity={entity}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{debug && (
|
{debug && (
|
||||||
<Crosshair x={entity.Position.x} y={entity.Position.y} />
|
<Crosshair x={entity.Position.x} y={entity.Position.y} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -159,6 +159,11 @@ export default function Ui({disconnected}) {
|
||||||
for (const id in payload.ecs) {
|
for (const id in payload.ecs) {
|
||||||
const entity = ecs.get(id);
|
const entity = ecs.get(id);
|
||||||
const update = payload.ecs[id];
|
const update = payload.ecs[id];
|
||||||
|
if (update.Sound?.play) {
|
||||||
|
for (const sound of update.Sound.play) {
|
||||||
|
(new Audio(sound)).play();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (update?.MainEntity) {
|
if (update?.MainEntity) {
|
||||||
setMainEntity(localMainEntity = id);
|
setMainEntity(localMainEntity = id);
|
||||||
}
|
}
|
||||||
|
|
21
package-lock.json
generated
21
package-lock.json
generated
|
@ -7,6 +7,7 @@
|
||||||
"name": "silphius-next",
|
"name": "silphius-next",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@msgpack/msgpack": "^3.0.0-beta2",
|
"@msgpack/msgpack": "^3.0.0-beta2",
|
||||||
|
"@pixi/particle-emitter": "^5.0.8",
|
||||||
"@pixi/react": "^7.1.2",
|
"@pixi/react": "^7.1.2",
|
||||||
"@pixi/spritesheet": "^7.4.2",
|
"@pixi/spritesheet": "^7.4.2",
|
||||||
"@pixi/tilemap": "^4.1.0",
|
"@pixi/tilemap": "^4.1.0",
|
||||||
|
@ -3419,6 +3420,26 @@
|
||||||
"@pixi/sprite": "7.4.2"
|
"@pixi/sprite": "7.4.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@pixi/particle-emitter": {
|
||||||
|
"version": "5.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pixi/particle-emitter/-/particle-emitter-5.0.8.tgz",
|
||||||
|
"integrity": "sha512-OzuZ4+esQo+zJ0u3htuNHHMAE8Ixmr3nz3tEfrTGZHje1vnGyie3ANQj9F0V4OM47oi9jd70njVCmeb7bTkS9A==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@pixi/constants": ">=6.0.4 <8.0.0",
|
||||||
|
"@pixi/core": ">=6.0.4 <8.0.0",
|
||||||
|
"@pixi/display": ">=6.0.4 <8.0.0",
|
||||||
|
"@pixi/math": ">=6.0.4 <8.0.0",
|
||||||
|
"@pixi/sprite": ">=6.0.4 <8.0.0",
|
||||||
|
"@pixi/ticker": ">=6.0.4 <8.0.0"
|
||||||
|
},
|
||||||
|
"workspaces": {
|
||||||
|
"packages": [
|
||||||
|
"./",
|
||||||
|
"test/pixi-v6-iife",
|
||||||
|
"test/pixi-v6-module"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@pixi/prepare": {
|
"node_modules/@pixi/prepare": {
|
||||||
"version": "7.4.2",
|
"version": "7.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-7.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-7.4.2.tgz",
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@msgpack/msgpack": "^3.0.0-beta2",
|
"@msgpack/msgpack": "^3.0.0-beta2",
|
||||||
|
"@pixi/particle-emitter": "^5.0.8",
|
||||||
"@pixi/react": "^7.1.2",
|
"@pixi/react": "^7.1.2",
|
||||||
"@pixi/spritesheet": "^7.4.2",
|
"@pixi/spritesheet": "^7.4.2",
|
||||||
"@pixi/tilemap": "^4.1.0",
|
"@pixi/tilemap": "^4.1.0",
|
||||||
|
|
BIN
public/assets/hoe/dig.wav
Normal file
BIN
public/assets/hoe/dig.wav
Normal file
Binary file not shown.
|
@ -1,4 +1,4 @@
|
||||||
const {Controlled, Position, Sprite, Wielder} = wielder
|
const {Controlled, Emitter, Position, Sound, Sprite, Wielder} = wielder
|
||||||
const {TileLayers} = ecs.get(1)
|
const {TileLayers} = ecs.get(1)
|
||||||
const layer = TileLayers.layer(0)
|
const layer = TileLayers.layer(0)
|
||||||
const projected = Wielder.project(Position.tile, item.tool.projection)
|
const projected = Wielder.project(Position.tile, item.tool.projection)
|
||||||
|
@ -6,7 +6,105 @@ const projected = Wielder.project(Position.tile, item.tool.projection)
|
||||||
Controlled.locked = 1;
|
Controlled.locked = 1;
|
||||||
const [, direction] = Sprite.animation.split(':');
|
const [, direction] = Sprite.animation.split(':');
|
||||||
|
|
||||||
|
const dirtParticles = {
|
||||||
|
behaviors: [
|
||||||
|
{
|
||||||
|
type: 'moveAcceleration',
|
||||||
|
config: {
|
||||||
|
accel: {
|
||||||
|
x: 0,
|
||||||
|
y: 200,
|
||||||
|
},
|
||||||
|
minStart: 0,
|
||||||
|
maxStart: 0,
|
||||||
|
rotate: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'moveSpeed',
|
||||||
|
config: {
|
||||||
|
speed: {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
time: 0,
|
||||||
|
value: 60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
time: 1,
|
||||||
|
value: 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'rotation',
|
||||||
|
config: {
|
||||||
|
accel: 0,
|
||||||
|
minSpeed: 0,
|
||||||
|
maxSpeed: 0,
|
||||||
|
minStart: 225,
|
||||||
|
maxStart: 320
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'scale',
|
||||||
|
config: {
|
||||||
|
scale: {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
value: 0.25,
|
||||||
|
time: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 0.125,
|
||||||
|
time: 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'textureSingle',
|
||||||
|
config: {
|
||||||
|
texture: 'tileset/7',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lifetime: {
|
||||||
|
min: 0.25,
|
||||||
|
max: 0.25,
|
||||||
|
},
|
||||||
|
frequency: 0.01,
|
||||||
|
emitterLifetime: 0.25,
|
||||||
|
pos: {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
for (let i = 0; i < 2; ++i) {
|
for (let i = 0; i < 2; ++i) {
|
||||||
|
Sound.play('/assets/hoe/dig.wav');
|
||||||
|
for (let i = 0; i < projected.length; ++i) {
|
||||||
|
Emitter.emit({
|
||||||
|
...dirtParticles,
|
||||||
|
behaviors: [
|
||||||
|
...dirtParticles.behaviors,
|
||||||
|
{
|
||||||
|
type: 'spawnShape',
|
||||||
|
config: {
|
||||||
|
type: 'rect',
|
||||||
|
data: {
|
||||||
|
x: projected[i].x * layer.tileSize.x,
|
||||||
|
y: projected[i].y * layer.tileSize.y,
|
||||||
|
w: layer.tileSize.x,
|
||||||
|
h: layer.tileSize.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
Sprite.animation = ['moving', direction].join(':');
|
Sprite.animation = ['moving', direction].join(':');
|
||||||
await wait(300)
|
await wait(300)
|
||||||
Sprite.animation = ['idle', direction].join(':');
|
Sprite.animation = ['idle', direction].join(':');
|
||||||
|
|
Loading…
Reference in New Issue
Block a user