import { System, SystemNames } from "."; import { Game } from ".."; import { Entity, EntityNames } from "../entities"; import { BoundingBox, ComponentNames, Grid } from "../components"; const collisionMap: Record> = { [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( ComponentNames.BoundingBox, ); let collidingGrid = entity.hasComponent(ComponentNames.Grid) ? entity.getComponent(ComponentNames.Grid) : null; const collidingWith: Entity[] = []; game.forEachEntityWithComponent( ComponentNames.BoundingBox, (otherEntity) => { const otherBoundingBox = otherEntity.getComponent( ComponentNames.BoundingBox, ); let otherGrid = otherEntity.hasComponent(ComponentNames.Grid) ? otherEntity.getComponent(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(); } }