1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
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]),
[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<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;
}
[entity, otherEntity].forEach((e) => {
if (!e.hasComponent(ComponentNames.Colliding)) {
return;
}
const colliding = e.getComponent<Colliding>(ComponentNames.Colliding);
if (colliding?.onCollision) {
colliding.onCollision(game, e === entity ? otherEntity : entity);
}
});
}
}
|