feat: emitter
This commit is contained in:
parent
309c94bbfc
commit
702650e04e
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: {},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -167,6 +167,7 @@ export default class Engine {
|
|||
Controlled: {},
|
||||
Direction: {direction: 2},
|
||||
Ecs: {path: join('homesteads', `${id}`)},
|
||||
Emitter: {},
|
||||
Forces: {},
|
||||
Inventory: {
|
||||
slots: {
|
||||
|
|
|
@ -42,11 +42,18 @@ export default function EcsComponent() {
|
|||
}
|
||||
const updatedEntities = {...entities};
|
||||
for (const id in payload.ecs) {
|
||||
if (false === payload.ecs[id]) {
|
||||
const update = payload.ecs[id];
|
||||
if (false === update) {
|
||||
delete updatedEntities[id];
|
||||
}
|
||||
else {
|
||||
updatedEntities[id] = ecs.get(id);
|
||||
if (update.Emitter?.emit) {
|
||||
updatedEntities[id].Emitter.emitting = {
|
||||
...updatedEntities[id].Emitter.emitting,
|
||||
...update.Emitter.emit,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
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 Emitter from './emitter.jsx';
|
||||
import Sprite from './sprite.jsx';
|
||||
|
||||
function Crosshair({x, y}) {
|
||||
|
@ -40,9 +41,16 @@ export default function Entities({entities}) {
|
|||
<Container
|
||||
key={id}
|
||||
>
|
||||
<Sprite
|
||||
entity={entity}
|
||||
/>
|
||||
{entity.Sprite && (
|
||||
<Sprite
|
||||
entity={entity}
|
||||
/>
|
||||
)}
|
||||
{entity.Emitter && (
|
||||
<Emitter
|
||||
entity={entity}
|
||||
/>
|
||||
)}
|
||||
{debug && (
|
||||
<Crosshair x={entity.Position.x} y={entity.Position.y} />
|
||||
)}
|
||||
|
|
21
package-lock.json
generated
21
package-lock.json
generated
|
@ -7,6 +7,7 @@
|
|||
"name": "silphius-next",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^3.0.0-beta2",
|
||||
"@pixi/particle-emitter": "^5.0.8",
|
||||
"@pixi/react": "^7.1.2",
|
||||
"@pixi/spritesheet": "^7.4.2",
|
||||
"@pixi/tilemap": "^4.1.0",
|
||||
|
@ -3419,6 +3420,26 @@
|
|||
"@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": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-7.4.2.tgz",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^3.0.0-beta2",
|
||||
"@pixi/particle-emitter": "^5.0.8",
|
||||
"@pixi/react": "^7.1.2",
|
||||
"@pixi/spritesheet": "^7.4.2",
|
||||
"@pixi/tilemap": "^4.1.0",
|
||||
|
|
Loading…
Reference in New Issue
Block a user