Skip to content

Commit 9880659

Browse files
alqubopagoru
andauthored
feat(queues): engine working with queues (#22)
* wip #19 * types and tests working again 🏷️ ✅ * types and tests working again 🏷️ ✅ * feat(queues): engine working with queues * feat(queues): engine working with queues * feat(queues): engine working with queues * feat(queues): tests working again ✅ * feat(queues): get next loop with idealTick * feat(queues): Updated onTick function * feat(queues): fix types and change README.md --------- Co-authored-by: pagoru <pagoru@gmail.com>
1 parent caded67 commit 9880659

7 files changed

Lines changed: 515 additions & 125 deletions

File tree

README.md

Lines changed: 108 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -28,54 +28,114 @@ Install the package with npm:
2828
npm install darker-engine
2929
```
3030

31-
### Code Example
31+
## Concepts
32+
33+
### Action Queue System
34+
35+
This engine implements an action queue with three levels of priority: `Priority.HIGH`, `Priority.MEDIUM`, `Priority.LOW`.
36+
Actions are added to the queue and processed based on their priority.
37+
38+
#### Config
39+
With `Engine.load` config we can specify how many ticks we want per second. By default, is 60
40+
41+
```ts
42+
await Engine.load({
43+
ticksPerSecond: 40,
44+
})
45+
```
46+
47+
With `Engine.onTick` we can sets a callback function that is run on each iteration of the loop.
48+
The callback function receives an object with the result of the last processed action, the time (`ms`) the iteration took, and the % usage of the tick.
49+
50+
```ts
51+
Engine.onTick(({usage, ms, status}) => {
52+
console.log({ms, usage, actionId: status?.id})
53+
})
54+
// -> { ms: 2, usage: 0.02, actionId: 1 }
55+
```
56+
57+
#### Add Actions To Queue
58+
When we use `addEntity`, `removeEntity`, `entity.updateComponent` and `entity.removeComponent` we can specify if we want to perform the action immediately or assign it a priority.
59+
60+
By default, they are added to the queue and assigned a medium priority (`Priority.MEDIUM`)
61+
62+
```ts
63+
// Action added to HIGH priority queue
64+
await Engine.addEntity({
65+
priority: Priority.HIGH,
66+
entities: [exampleEntity()]
67+
})
68+
69+
// Action that is executed immediately without depending on the queue
70+
await Engine.addEntity({
71+
force: true,
72+
entities: [exampleEntity()]
73+
})
74+
```
75+
76+
## Code Example
3277

3378
#### Declaration
3479

3580
```ts
36-
import { engine as darkerEngine } from "darker-engine";
81+
import { engine } from "darker-engine";
3782

38-
export const Engine = darkerEngine<IEntities, IComponents, ComponentData>();
83+
export const Engine = engine<IEntities, IComponents, ComponentData>();
3984

4085
Engine.setSystems(...[]);
4186

42-
Engine.load();
87+
Engine.load({
88+
ticksPerSecond: 40
89+
});
4390
```
4491

4592
#### Enums
4693

4794
```ts
4895
enum EntityType {
49-
EXAMPLE,
96+
EXAMPLE_ENTITY,
5097
}
5198

5299
enum Components {
53-
EXAMPLE_COMPONENT = "EXAMPLE_COMPONENT",
100+
EXAMPLE_COMPONENT,
101+
OTHER_COMPONENT
54102
}
103+
104+
type ComponentData = {
105+
[Components.EXAMPLE_COMPONENT]: {
106+
foo: string;
107+
},
108+
[Components.OTHER_COMPONENT]: {
109+
bar: number;
110+
};
111+
};
55112
```
56113

57114
#### Entity
58115

59116
```ts
60-
import { EntityType } from "darker-engine";
117+
import { EntityTypeFunction } from "darker-engine";
61118

62-
const exampleEntity = (): EntityType<IEntities, IComponents, ComponentData> => ({
63-
id: Engine.getUID(),
64-
type: EntityType.EXAMPLE,
65-
data: {},
66-
components: [],
67-
});
119+
const exampleEntity: EntityTypeFunction<IEntities, IComponents, ComponentData, any> = () => ({
120+
type: Entities.EXAMPLE_ENTITY,
121+
data: {
122+
[Components.EXAMPLE_COMPONENT]: {
123+
foo: "faa",
124+
}
125+
},
126+
components: [Components.EXAMPLE_COMPONENT],
127+
})
68128
```
69129

70130
#### Systems
71131

72132
```ts
73133
import { SystemFunction } from "darker-engine";
74134

75-
const exampleSystem: SystemFunction<IComponents> = () => {
76-
const onAdd = (entityId: number) => {};
77-
const onUpdate = (entityId: number, component: string) => {};
78-
const onRemove = (entityId: number) => {};
135+
const exampleSystem: SystemFunction<Components> = async () => {
136+
const onAdd = async (entityId: number) => {};
137+
const onUpdate = async (entityId: number, component: string) => {};
138+
const onRemove = async (entityId: number) => {};
79139

80140
return {
81141
components: [],
@@ -89,11 +149,7 @@ const exampleSystem: SystemFunction<IComponents> = () => {
89149
#### Full code
90150

91151
```ts
92-
import {
93-
engine as darkerEngine,
94-
EntityType,
95-
SystemFunction,
96-
} from "darker-engine";
152+
import {engine, EntityTypeFunction, SystemFunction} from "darker-engine";
97153

98154
enum IEntities {
99155
EXAMPLE_ENTITY,
@@ -113,10 +169,9 @@ type ComponentData = {
113169
};
114170
};
115171

116-
export const Engine = darkerEngine<IEntities, IComponents, ComponentData>()
172+
export const Engine = engine<IEntities, IComponents, ComponentData>()
117173

118-
const exampleEntity: EntityTypeFunction<IEntities, IComponents, ComponentData> = () => ({
119-
id: Engine.getUID(),
174+
const exampleEntity: EntityTypeFunction<IEntities, IComponents, ComponentData, void> = () => ({
120175
type: IEntities.EXAMPLE_ENTITY,
121176
data: {
122177
[IComponents.EXAMPLE_COMPONENT]: {
@@ -126,12 +181,15 @@ const exampleEntity: EntityTypeFunction<IEntities, IComponents, ComponentData> =
126181
components: [IComponents.EXAMPLE_COMPONENT],
127182
})
128183

129-
const exampleSystem: SystemFunction<IComponents> = () => {
184+
const exampleSystem: SystemFunction<IComponents> = async () => {
130185
let interval: number
131186

132-
const onLoad = () => {
187+
const onLoad = async () => {
133188
console.log("welcome!");
134-
Engine.addEntity(exampleEntity());
189+
190+
await Engine.addEntity({
191+
entities: [exampleEntity()]
192+
})
135193

136194
interval = setInterval(() => {
137195
const entityList = Engine.getEntityList();
@@ -147,33 +205,39 @@ const exampleSystem: SystemFunction<IComponents> = () => {
147205
}, 5000);
148206
}
149207

150-
const onDestroy = () => {
208+
const onDestroy = async () => {
151209
clearInterval(interval);
152210
console.log("bye!");
153211
}
154212

155-
const onAdd = (id: number) => {
213+
const onAdd = async (id: number) => {
156214
const entity = Engine.getEntity(id);
157-
entity.updateComponent(IComponents.EXAMPLE_COMPONENT, { foo: 'fii'});
215+
if(entity) {
216+
await entity.updateComponent({
217+
component: IComponents.EXAMPLE_COMPONENT,
218+
data: {foo: 'fii2'}
219+
})
220+
}
158221
}
159222

160-
const onUpdate = (id: number, component?: IComponents) => {
223+
const onUpdate = async (id: number, component?: IComponents) => {
161224
const entity = Engine.getEntity(id);
162225

163-
if (component !== IComponents.EXAMPLE_COMPONENT) return;
226+
if (!entity || component !== IComponents.EXAMPLE_COMPONENT) return;
164227

165228
const { foo } = entity.getComponent(IComponents.EXAMPLE_COMPONENT);
166229
if (foo === "fii" && !entity.hasComponent(IComponents.OTHER_COMPONENT)) {
167-
entity.removeComponent(IComponents.EXAMPLE_COMPONENT);
230+
await entity.removeComponent({
231+
component: IComponents.EXAMPLE_COMPONENT
232+
})
168233
}
169234
}
170235

171-
const onRemove = (entityId: number) => {
172-
Engine.removeEntity(entityId);
236+
const onRemove = async (entityId: number) => {
237+
await Engine.removeEntity({ids: [entityId]})
173238
};
174239

175240
return {
176-
id: Engine.getUID(),
177241
components: [IComponents.EXAMPLE_COMPONENT],
178242
onLoad,
179243
onDestroy,
@@ -183,7 +247,12 @@ const exampleSystem: SystemFunction<IComponents> = () => {
183247
}
184248
}
185249

186-
Engine.setSystems(exampleSystem);
187-
Engine.load()
250+
await Engine.setSystems(exampleSystem);
251+
await Engine.load({
252+
ticksPerSecond: 2,
253+
})
188254

255+
Engine.onTick(({usage, ms, status}) => {
256+
console.log({ms, usage, actionId: status?.id})
257+
})
189258
```

0 commit comments

Comments
 (0)