import { System, SystemNames } from "."; import { Game } from ".."; import { Entity, EntityNames } from "../entities"; import { BoundingBox, Colliding, ComponentNames, Grid } from "../components"; const collisionMap: Record> = { [EntityNames.Key]: new Set([EntityNames.LockedDoor]), [EntityNames.Curry]: new Set([EntityNames.Player]), [EntityNames.FunctionApplication]: new Set([EntityNames.FunctionBox]), }; 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; } [entity, otherEntity].forEach((e) => { if (!e.hasComponent(ComponentNames.Colliding)) { return; } const colliding = e.getComponent(ComponentNames.Colliding); if (colliding?.onCollision) { colliding.onCollision(game, e === entity ? otherEntity : entity); } }); } }