-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptimizedCollision.js
More file actions
80 lines (73 loc) · 2.67 KB
/
optimizedCollision.js
File metadata and controls
80 lines (73 loc) · 2.67 KB
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
import {debug, Entities, Component, System, DeleteComponent, TransformComponent, Game} from './engine.js';
import {Vector} from './vector.js';
import {Quadtree} from './quadtree.js';
export class CollisionComponent extends Component {
constructor(x,y) {
super("collision");
this.x = x;
this.y = y;
this.collisionCallbacks = {};
}
registerCallback(componentId, callback) {
this.collisionCallbacks[componentId] = callback;
}
handleCollision(entity, collision, normal) {
for(const key of Object.keys(this.collisionCallbacks)){
if(collision.hasComponent(key)){
const callback = this.collisionCallbacks[key];
callback(entity, collision);
}
}
}
hasCallback(entity){
for(const key of Object.keys(this.collisionCallbacks)){
if(entity.hasComponent(key)){
return true;
}
}
return false;
}
}
export class CollisionSystem extends System {
constructor() {
super("collisoin")
this.quadtree = new Quadtree(0,0,800,600);
}
update(entities, dt) {
// clear the quadtree
this.quadtree.clear();
// Get an array of entities with collision components
const colliders = Array.from(entities.values()).filter(entity => entity.hasComponent('collision'));
for (const collider of colliders) {
const transform = collider.getComponent("transform");
const collision = collider.getComponent("collision");
collision.x = transform.x;
collision.y = transform.y;
this.quadtree.insert(collision);
}
for (const collider of colliders) {
const collision = collider.getComponent("collision");
const potentialColliders = this.quadtree.retrieve(collision);
for (const potentialCollider of potentialColliders) {
if (potentialCollider === collision) continue;
const transform1 = collider.getComponent("transform");
const transform2 = potentialCollider.getComponent("transform");
if (collision.hasCallback(potentialCollider) || potentialCollider.hasCallback(collision)) {
if (this.checkCollision(collision.x, collision.y, transform2.x, transform2.y)) {
collision.handleCollision(collider, potentialCollider);
potentialCollider.handleCollision(potentialCollider, collider);
}
}
}
}
}
checkCollision(x, y, polygon) {
let isInside = false;
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
if (polygon[i].y > y !== polygon[j].y > y && x < (polygon[j].x - polygon[i].x) * (y - polygon[i].y) / (polygon[j].y - polygon[i].y) + polygon[i].x) {
isInside = !isInside;
}
}
return isInside;
}
}