summaryrefslogtreecommitdiff
path: root/src/engine/systems/Collision.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/systems/Collision.ts')
-rw-r--r--src/engine/systems/Collision.ts103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/engine/systems/Collision.ts b/src/engine/systems/Collision.ts
new file mode 100644
index 0000000..7b1b963
--- /dev/null
+++ b/src/engine/systems/Collision.ts
@@ -0,0 +1,103 @@
+import { System, SystemNames } from ".";
+import { Game } from "..";
+import { Entity, EntityNames } from "../entities";
+import { BoundingBox, Colliding, ComponentNames, Grid } from "../components";
+
+const collisionMap: Record<string, Set<string>> = {
+ [EntityNames.Key]: new Set([EntityNames.LockedDoor]),
+ [EntityNames.Curry]: new Set([EntityNames.Player]),
+};
+
+export class Collision extends System {
+ static canCollide(entityName: string, otherEntityName: string) {
+ if (collisionMap[entityName]) {
+ return collisionMap[entityName].has(otherEntityName);
+ }
+ return collisionMap[otherEntityName]?.has(entityName) ?? false;
+ }
+
+ constructor() {
+ super(SystemNames.Collision);
+ }
+
+ public update(_dt: number, game: Game) {
+ game.forEachEntityWithComponent(ComponentNames.Colliding, (entity) => {
+ if (!entity.hasComponent(ComponentNames.BoundingBox)) {
+ return;
+ }
+ const collidingBox = entity.getComponent<BoundingBox>(
+ ComponentNames.BoundingBox,
+ );
+ let collidingGrid = entity.hasComponent(ComponentNames.Grid)
+ ? entity.getComponent<Grid>(ComponentNames.Grid)
+ : null;
+
+ const collidingWith: Entity[] = [];
+ game.forEachEntityWithComponent(
+ ComponentNames.BoundingBox,
+ (otherEntity) => {
+ const otherBoundingBox = otherEntity.getComponent<BoundingBox>(
+ ComponentNames.BoundingBox,
+ );
+ let otherGrid = otherEntity.hasComponent(ComponentNames.Grid)
+ ? otherEntity.getComponent<Grid>(ComponentNames.Grid)
+ : null;
+
+ if (collidingGrid && otherGrid) {
+ if (
+ collidingGrid.gridPosition.x === otherGrid.gridPosition.x &&
+ collidingGrid.gridPosition.y === otherGrid.gridPosition.y
+ ) {
+ collidingWith.push(otherEntity);
+ }
+ return;
+ }
+
+ if (collidingBox.isCollidingWith(otherBoundingBox)) {
+ collidingWith.push(otherEntity);
+ }
+ },
+ );
+
+ for (const collision of collidingWith) {
+ this.handleCollision(entity, collision, game);
+ }
+ });
+ }
+
+ private handleCollision(entity: Entity, otherEntity: Entity, game: Game) {
+ if (!Collision.canCollide(entity.name, otherEntity.name)) {
+ return;
+ }
+
+ const keyDoorPair = [EntityNames.Key, EntityNames.LockedDoor].map((x) =>
+ [entity, otherEntity].find((y) => y.name === x),
+ );
+ const [key, door] = keyDoorPair;
+ if (key && door) {
+ this.handleKeyDoorCollision(key, door, game);
+ }
+
+ const curryPlayerPair = [EntityNames.Curry, EntityNames.Player].map((x) =>
+ [entity, otherEntity].find((y) => y.name === x),
+ );
+ const [curry, player] = curryPlayerPair;
+ if (curry && player) {
+ this.handleCurryPlayerCollision(curry, player, game);
+ }
+ }
+
+ private handleKeyDoorCollision(key: Entity, door: Entity, game: Game) {
+ game.removeEntity(key.id);
+ game.removeEntity(door.id);
+ }
+
+ private handleCurryPlayerCollision(
+ curry: Entity,
+ _player: Entity,
+ game: Game,
+ ) {
+ game.removeEntity(curry.id);
+ game.stop();
+ }
+}