summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-03-01 16:45:58 -0700
committerElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-03-01 16:45:58 -0700
commitaa08a8943a9a2d4a0e51893eebe6900bca7a7251 (patch)
tree1bfd2505e7675af45ec1e56434a6549e98d42e7f
parent5148ee2063846d37f9152a9dfa64fcd40cc0454b (diff)
downloadthe-abstraction-engine-aa08a8943a9a2d4a0e51893eebe6900bca7a7251.tar.gz
the-abstraction-engine-aa08a8943a9a2d4a0e51893eebe6900bca7a7251.zip
ecs init
-rw-r--r--src/engine/components/Component.ts7
-rw-r--r--src/engine/components/ComponentNames.ts3
-rw-r--r--src/engine/components/index.ts2
-rw-r--r--src/engine/entities/Entity.ts34
-rw-r--r--src/engine/entities/EntityNames.ts5
-rw-r--r--src/engine/entities/index.ts2
-rw-r--r--src/engine/index.ts90
-rw-r--r--src/engine/systems/System.ts11
-rw-r--r--src/engine/systems/SystemNames.ts7
-rw-r--r--src/engine/systems/index.ts2
10 files changed, 163 insertions, 0 deletions
diff --git a/src/engine/components/Component.ts b/src/engine/components/Component.ts
new file mode 100644
index 0000000..7331982
--- /dev/null
+++ b/src/engine/components/Component.ts
@@ -0,0 +1,7 @@
+export abstract class Component {
+ public readonly name: string;
+
+ constructor(name: string) {
+ this.name = name;
+ }
+}
diff --git a/src/engine/components/ComponentNames.ts b/src/engine/components/ComponentNames.ts
new file mode 100644
index 0000000..90dfb90
--- /dev/null
+++ b/src/engine/components/ComponentNames.ts
@@ -0,0 +1,3 @@
+export namespace ComponentNames {
+ export const Sprite = "Sprite";
+}
diff --git a/src/engine/components/index.ts b/src/engine/components/index.ts
new file mode 100644
index 0000000..a2fd5d1
--- /dev/null
+++ b/src/engine/components/index.ts
@@ -0,0 +1,2 @@
+export * from "./Component";
+export * from "./ComponentNames";
diff --git a/src/engine/entities/Entity.ts b/src/engine/entities/Entity.ts
new file mode 100644
index 0000000..18ee5d0
--- /dev/null
+++ b/src/engine/entities/Entity.ts
@@ -0,0 +1,34 @@
+import { type Component } from "../components";
+
+const randomId = () => (Math.random() * 1_000_000_000).toString();
+
+export abstract class Entity {
+ public id: string;
+ public components: Map<string, Component>;
+ public name: string;
+
+ constructor(name: string, id: string = randomId()) {
+ this.name = name;
+ this.id = id;
+ this.components = new Map();
+ }
+
+ public addComponent(component: Component) {
+ this.components.set(component.name, component);
+ }
+
+ public getComponent<T extends Component>(name: string): T {
+ if (!this.hasComponent(name)) {
+ throw new Error("Entity does not have component " + name);
+ }
+ return this.components.get(name) as T;
+ }
+
+ public getComponents(): Component[] {
+ return Array.from(this.components.values());
+ }
+
+ public hasComponent(name: string): boolean {
+ return this.components.has(name);
+ }
+}
diff --git a/src/engine/entities/EntityNames.ts b/src/engine/entities/EntityNames.ts
new file mode 100644
index 0000000..59010fc
--- /dev/null
+++ b/src/engine/entities/EntityNames.ts
@@ -0,0 +1,5 @@
+export namespace EntityNames {
+ export const Player = "Player";
+ export const Wall = "Wall";
+ export const Ball = "Ball";
+}
diff --git a/src/engine/entities/index.ts b/src/engine/entities/index.ts
new file mode 100644
index 0000000..ee26a63
--- /dev/null
+++ b/src/engine/entities/index.ts
@@ -0,0 +1,2 @@
+export * from "./Entity";
+export * from "./EntityNames";
diff --git a/src/engine/index.ts b/src/engine/index.ts
new file mode 100644
index 0000000..2df9f17
--- /dev/null
+++ b/src/engine/index.ts
@@ -0,0 +1,90 @@
+import { Entity } from "./entities";
+import { System } from "./systems";
+
+export class Game {
+ private systemOrder: string[];
+
+ private running: boolean;
+ private lastTimeStamp: number;
+
+ public entities: Map<string, Entity>;
+ public systems: Map<string, System>;
+ public componentEntities: Map<string, Set<string>>;
+
+ constructor() {
+ this.lastTimeStamp = performance.now();
+ this.running = false;
+ this.systemOrder = [];
+ this.systems = new Map();
+ this.entities = new Map();
+ this.componentEntities = new Map();
+ }
+
+ public start() {
+ this.lastTimeStamp = performance.now();
+ this.running = true;
+ }
+
+ public addEntity(entity: Entity) {
+ this.entities.set(entity.id, entity);
+ }
+
+ public getEntity(id: string): Entity | undefined {
+ return this.entities.get(id);
+ }
+
+ public removeEntity(id: string) {
+ this.entities.delete(id);
+ }
+
+ public forEachEntityWithComponent(
+ componentName: string,
+ callback: (entity: Entity) => void,
+ ) {
+ this.componentEntities.get(componentName)?.forEach((entityId) => {
+ const entity = this.getEntity(entityId);
+ if (!entity) return;
+
+ callback(entity);
+ });
+ }
+
+ public addSystem(system: System) {
+ if (!this.systemOrder.includes(system.name)) {
+ this.systemOrder.push(system.name);
+ }
+ this.systems.set(system.name, system);
+ }
+
+ public getSystem<T>(name: string): T {
+ return this.systems.get(name) as unknown as T;
+ }
+
+ public doGameLoop(timeStamp: number) {
+ if (!this.running) {
+ return;
+ }
+
+ const dt = timeStamp - this.lastTimeStamp;
+ this.lastTimeStamp = timeStamp;
+
+ // rebuild the Component -> { Entity } map
+ this.componentEntities.clear();
+ this.entities.forEach((entity) =>
+ entity.getComponents().forEach((component) => {
+ if (!this.componentEntities.has(component.name)) {
+ this.componentEntities.set(
+ component.name,
+ new Set<string>([entity.id]),
+ );
+ return;
+ }
+ this.componentEntities.get(component.name)?.add(entity.id);
+ }),
+ );
+
+ this.systemOrder.forEach((systemName) => {
+ this.systems.get(systemName)?.update(dt, this);
+ });
+ }
+}
diff --git a/src/engine/systems/System.ts b/src/engine/systems/System.ts
new file mode 100644
index 0000000..9852276
--- /dev/null
+++ b/src/engine/systems/System.ts
@@ -0,0 +1,11 @@
+import { Game } from "..";
+
+export abstract class System {
+ public readonly name: string;
+
+ constructor(name: string) {
+ this.name = name;
+ }
+
+ abstract update(dt: number, game: Game): void;
+}
diff --git a/src/engine/systems/SystemNames.ts b/src/engine/systems/SystemNames.ts
new file mode 100644
index 0000000..41207a4
--- /dev/null
+++ b/src/engine/systems/SystemNames.ts
@@ -0,0 +1,7 @@
+export namespace SystemNames {
+ export const Render = "Render";
+ export const Physics = "Physics";
+ export const Input = "Input";
+ export const Collision = "Collision";
+ export const WallBounds = "WallBounds";
+}
diff --git a/src/engine/systems/index.ts b/src/engine/systems/index.ts
new file mode 100644
index 0000000..989dc7f
--- /dev/null
+++ b/src/engine/systems/index.ts
@@ -0,0 +1,2 @@
+export * from "./SystemNames";
+export * from "./System";