Skip to content

Commit

Permalink
feat(engine/loop): Added pause and resume functions (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
alqubo authored Mar 20, 2024
1 parent 3a2209a commit 436e9d6
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 4 deletions.
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ Engine.onTick(({usage, ms, status}) => {
// -> { ms: 2, usage: 0.02, actionId: 1 }
```

With `Engine.pause` you can pause the entire engine loop. All systems will call `onPause` function before.

```ts
await Engine.pause()
```

With `Engine.resume` you can start again the engine loop. All systems will call `onResume` function after the loop restarts.

```ts
await Engine.resume()
```

#### Add Actions To Queue
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.

Expand Down Expand Up @@ -237,9 +249,19 @@ const exampleSystem: SystemFunction<IComponents> = async () => {
await Engine.removeEntity({ids: [entityId]})
};

const onResume = async () => {
console.log('system wake up')
}

const onPause = async () => {
console.log('system paused')
}

return {
components: [IComponents.EXAMPLE_COMPONENT],
onLoad,
onResume,
onPause,
onDestroy,
onAdd,
onUpdate,
Expand All @@ -252,7 +274,7 @@ await Engine.load({
ticksPerSecond: 2,
})

Engine.onTick(({usage, ms, status}) => {
console.log({ms, usage, actionId: status?.id})
Engine.onTick(({usage, ms, status, tickCount}) => {
console.log({ ms, usage, status, tickCount})
})
```
26 changes: 24 additions & 2 deletions src/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,25 @@ export const engine = <
}
};

const pause = async () => {
for await (const system of systems) {
await system?.onPause?.();
}

loopRunning = false;
};

const resume = async () => {
lastTick = Date.now();
idealTick = Date.now();
loopRunning = true;
loop();

for await (const system of systems) {
await system?.onResume?.();
}
};

const hardReload = async () => {
for await (const system of [...systems].reverse().filter(Boolean)) {
const entities = systemEntitiesMap[system.id];
Expand Down Expand Up @@ -625,8 +644,6 @@ export const engine = <
};

const loop = async () => {
if (!loopRunning) return;

const now = Date.now();
const deltaTime = now - lastTick;

Expand All @@ -644,6 +661,8 @@ export const engine = <
if (_onTick) _onTick({ status, ms, usage, tickCount });

tickCount++;

if (!loopRunning) return;
loopId = setTimeout(loop, nextTick);
};

Expand All @@ -662,6 +681,9 @@ export const engine = <
clear,

load,
pause,
resume,

hardReload,

onTick,
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export interface EngineType<I, C extends string | number, D> {
clear: () => void;

load: (config?: LoadConfig) => Promise<void>;
pause: () => Promise<void>;
resume: () => Promise<void>;
hardReload: () => Promise<void>;

onTick: (cb: OnTickFunction) => void;
Expand All @@ -86,6 +88,8 @@ export interface SystemType<C> {
onRemove?: (id: number) => Promise<void>;

onLoad?: () => Promise<void>;
onResume?: () => Promise<void>;
onPause?: () => Promise<void>;
onDestroy?: () => Promise<void>;
}

Expand Down
34 changes: 34 additions & 0 deletions tests/system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ Deno.test('System', async (test) => {
const onLoadSystemAMock = spy(async () => {});
const onLoadSystemBMock = spy(async () => {});

const onPauseSystemAMock = spy(async () => {});
const onPauseSystemBMock = spy(async () => {});

const onResumeSystemAMock = spy(async () => {});
const onResumeSystemBMock = spy(async () => {});

const onDestroySystemAMock = spy(async () => {});
const onDestroySystemBMock = spy(async () => {});

Expand All @@ -38,6 +44,8 @@ Deno.test('System', async (test) => {
onUpdate: onUpdateSystemAMock,
onRemove: onRemoveSystemAMock,
onLoad: onLoadSystemAMock,
onPause: onPauseSystemAMock,
onResume: onResumeSystemAMock,
onDestroy: onDestroySystemAMock,
});

Expand All @@ -48,6 +56,8 @@ Deno.test('System', async (test) => {
onUpdate: onUpdateSystemBMock,
onRemove: onRemoveSystemBMock,
onLoad: onLoadSystemBMock,
onPause: onPauseSystemBMock,
onResume: onResumeSystemBMock,
onDestroy: onDestroySystemBMock,
});
await Engine.setSystems(systemA, systemB);
Expand Down Expand Up @@ -174,4 +184,28 @@ Deno.test('System', async (test) => {
Engine.clear();
});
});

await test.step('onPause', async (t) => {
await t.step('expect onPause to be called inside system', async () => {
await Engine.setSystems(systemA, systemB);
await Engine.pause();

assertSpyCall(onPauseSystemAMock, 0);
assertSpyCall(onPauseSystemBMock, 0);

Engine.clear();
});
});

await test.step('onResume', async (t) => {
await t.step('expect onResume to be called inside system', async () => {
await Engine.setSystems(systemA, systemB);
await Engine.resume();

assertSpyCall(onResumeSystemAMock, 0);
assertSpyCall(onResumeSystemBMock, 0);

Engine.clear();
});
});
});

0 comments on commit 436e9d6

Please sign in to comment.