2023-07-19 23:38:24 -04:00
|
|
|
import { Entity } from "./entities";
|
|
|
|
import { System } from "./systems";
|
|
|
|
|
|
|
|
export class Game {
|
|
|
|
private systemOrder: string[];
|
|
|
|
|
|
|
|
private running: boolean;
|
|
|
|
private lastTimeStamp: number;
|
|
|
|
|
2023-08-15 20:30:19 -04:00
|
|
|
public entities: Map<string, Entity>;
|
2023-07-20 23:47:32 -04:00
|
|
|
public systems: Map<string, System>;
|
2023-08-15 20:30:19 -04:00
|
|
|
public componentEntities: Map<string, Set<string>>;
|
2023-07-20 23:47:32 -04:00
|
|
|
|
2023-07-19 23:38:24 -04:00
|
|
|
constructor() {
|
2023-08-12 15:49:16 -04:00
|
|
|
this.lastTimeStamp = performance.now();
|
2023-07-19 23:38:24 -04:00
|
|
|
this.running = false;
|
|
|
|
this.systemOrder = [];
|
|
|
|
this.systems = new Map();
|
|
|
|
this.entities = new Map();
|
2023-07-20 23:47:32 -04:00
|
|
|
this.componentEntities = new Map();
|
2023-07-19 23:38:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public start() {
|
|
|
|
this.lastTimeStamp = performance.now();
|
|
|
|
this.running = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public addEntity(entity: Entity) {
|
|
|
|
this.entities.set(entity.id, entity);
|
|
|
|
}
|
|
|
|
|
2023-08-15 20:30:19 -04:00
|
|
|
public getEntity(id: string): Entity | undefined {
|
2023-07-19 23:38:24 -04:00
|
|
|
return this.entities.get(id);
|
|
|
|
}
|
|
|
|
|
2023-08-15 20:30:19 -04:00
|
|
|
public removeEntity(id: string) {
|
2023-07-19 23:38:24 -04:00
|
|
|
this.entities.delete(id);
|
|
|
|
}
|
|
|
|
|
2023-08-12 15:49:16 -04:00
|
|
|
public forEachEntityWithComponent(
|
|
|
|
componentName: string,
|
|
|
|
callback: (entity: Entity) => void,
|
|
|
|
) {
|
|
|
|
this.componentEntities.get(componentName)?.forEach((entityId) => {
|
|
|
|
const entity = this.getEntity(entityId);
|
|
|
|
if (!entity) return;
|
|
|
|
|
|
|
|
callback(entity);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-07-19 23:38:24 -04:00
|
|
|
public addSystem(system: System) {
|
|
|
|
if (!this.systemOrder.includes(system.name)) {
|
|
|
|
this.systemOrder.push(system.name);
|
|
|
|
}
|
|
|
|
this.systems.set(system.name, system);
|
|
|
|
}
|
|
|
|
|
2023-08-12 15:49:16 -04:00
|
|
|
public getSystem(name: string): System | undefined {
|
2023-07-19 23:38:24 -04:00
|
|
|
return this.systems.get(name);
|
|
|
|
}
|
|
|
|
|
2023-08-23 21:44:59 -04:00
|
|
|
public doGameLoop(timeStamp: number) {
|
2023-07-19 23:38:24 -04:00
|
|
|
if (!this.running) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const dt = timeStamp - this.lastTimeStamp;
|
|
|
|
this.lastTimeStamp = timeStamp;
|
|
|
|
|
2023-07-21 01:22:26 -04:00
|
|
|
// rebuild the Component -> { Entity } map
|
2023-07-20 23:47:32 -04:00
|
|
|
this.componentEntities.clear();
|
2023-07-19 23:38:24 -04:00
|
|
|
this.entities.forEach((entity) =>
|
|
|
|
entity.getComponents().forEach((component) => {
|
2023-07-20 23:47:32 -04:00
|
|
|
if (!this.componentEntities.has(component.name)) {
|
|
|
|
this.componentEntities.set(
|
|
|
|
component.name,
|
2023-08-15 20:30:19 -04:00
|
|
|
new Set<string>([entity.id]),
|
2023-07-20 23:47:32 -04:00
|
|
|
);
|
2023-07-19 23:38:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2023-08-12 15:49:16 -04:00
|
|
|
this.componentEntities.get(component.name)?.add(entity.id);
|
|
|
|
}),
|
2023-07-19 23:38:24 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
this.systemOrder.forEach((systemName) => {
|
2023-08-12 15:49:16 -04:00
|
|
|
this.systems.get(systemName)?.update(dt, this);
|
2023-07-19 23:38:24 -04:00
|
|
|
});
|
2023-08-23 21:44:59 -04:00
|
|
|
}
|
2023-07-19 23:38:24 -04:00
|
|
|
}
|