diff options
Diffstat (limited to 'src/engine/systems')
-rw-r--r-- | src/engine/systems/Collision.ts | 103 | ||||
-rw-r--r-- | src/engine/systems/Grid.ts | 36 | ||||
-rw-r--r-- | src/engine/systems/SystemNames.ts | 1 | ||||
-rw-r--r-- | src/engine/systems/index.ts | 1 |
4 files changed, 130 insertions, 11 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(); + } +} diff --git a/src/engine/systems/Grid.ts b/src/engine/systems/Grid.ts index 8756320..915335b 100644 --- a/src/engine/systems/Grid.ts +++ b/src/engine/systems/Grid.ts @@ -1,4 +1,4 @@ -import { System, SystemNames } from "."; +import { Collision, System, SystemNames } from "."; import { Game } from ".."; import { Entity } from "../entities"; import { PhysicsConstants } from "../config"; @@ -13,8 +13,8 @@ import { Coord2D, Direction, Dimension2D } from "../interfaces"; import { clamp } from "../utils"; export class Grid extends System { - private dimension: Dimension2D; - private grid: Set<string>[][] = []; + public dimension: Dimension2D; + public grid: Set<string>[][] = []; constructor( { width: columns, height: rows }: Dimension2D, @@ -108,10 +108,10 @@ export class Grid extends System { grid.movingDirection = Direction.NONE; entity.addComponent(grid); // default to not moving - let nextGridPosition = this.getNewGridPosition( + let [currentPosition, nextGridPosition] = [ gridPosition, - movingDirection, - ); + this.getNewGridPosition(gridPosition, movingDirection), + ]; const moving = new Set<string>(); moving.add(entity.id); @@ -122,11 +122,24 @@ export class Grid extends System { (id) => game.getEntity(id)!, ); - if ( - entities.some((entity) => - entity.hasComponent(ComponentNames.Colliding), + const collidingEntities = entities.filter((entity) => + entity.hasComponent(ComponentNames.Colliding), + ); + + if (collidingEntities.length > 0) { + // i.e. key going into a door or function going into an application + const allEntitiesInPreviousCellCanCollide = Array.from( + this.grid[currentPosition.y][currentPosition.x], ) - ) { + .map((id) => game.getEntity(id)!) + .every((entity) => + collidingEntities.every((collidingEntity) => + Collision.canCollide(entity.name, collidingEntity.name), + ), + ); + if (allEntitiesInPreviousCellCanCollide) { + break; + } moving.clear(); break; } @@ -148,6 +161,7 @@ export class Grid extends System { moving.add(pushableEntity.id); } + currentPosition = nextGridPosition; nextGridPosition = this.getNewGridPosition( nextGridPosition, movingDirection, @@ -324,7 +338,7 @@ export class Grid extends System { this.grid.forEach((row) => row.forEach((cell) => { for (const id of cell) { - if (movedEntities.has(id)) { + if (movedEntities.has(id) || !game.getEntity(id)) { cell.delete(id); } } diff --git a/src/engine/systems/SystemNames.ts b/src/engine/systems/SystemNames.ts index 85d1539..c96dc48 100644 --- a/src/engine/systems/SystemNames.ts +++ b/src/engine/systems/SystemNames.ts @@ -4,4 +4,5 @@ export namespace SystemNames { export const FacingDirection = "FacingDirection"; export const Grid = "Grid"; export const LambdaFactory = "LambdaFactory"; + export const Collision = "Collision"; } diff --git a/src/engine/systems/index.ts b/src/engine/systems/index.ts index 4490ee2..6ee5392 100644 --- a/src/engine/systems/index.ts +++ b/src/engine/systems/index.ts @@ -5,3 +5,4 @@ export * from "./Input"; export * from "./FacingDirection"; export * from "./Grid"; export * from "./LambdaFactory"; +export * from "./Collision"; |