s2maps-gpu
Version:
S2 Maps GPU - An open source, high-performance, and GPU-accelerated map engine for rendering large-scale, interactive maps.
94 lines (93 loc) • 3.06 kB
JavaScript
/**
* # Collision Tester
*
* Due to the nature of tile sizes keeping the quantity of nodes lower,
* collisions storage is a non-issue. Thus, we can do very basic collision detection tests
* and not worry about complexity.
*/
export default class CollisionTester {
nodes = [];
/** Clear all nodes for the next tile */
clear() {
this.nodes = [];
}
/**
* Insert if and only if there are no collisions with prior nodes
* If there is a collision, return true
* @param node - the node to insert
* @returns true if there is a collision with pre-existing nodes
*/
collides(node) {
let collision = false;
for (const existing of this.nodes) {
if (this.#collides(node, existing)) {
collision = true;
break;
}
}
if (!collision)
this.nodes.push(node);
return collision;
}
/**
* Check if two nodes collide using both square and round node checks
* @param a - the first node
* @param b - the second node
* @returns true if the nodes collide
*/
#collides(a, b) {
if (a.id === b.id)
return false;
if ('r' in a && 'r' in b)
return this.#collidesRoundRound(a, b);
else if ('r' in a)
return this.#collidesRoundSquare(a, b);
else if ('r' in b)
return this.#collidesRoundSquare(b, a);
else
return this.#collidesSquareSquare(a, b);
}
/**
* Check if two round nodes collide
* @param a - the first round node
* @param b - the second round node
* @returns true if the nodes collide
*/
#collidesRoundRound(a, b) {
for (const aNode of a.nodes) {
for (const bNode of b.nodes) {
const dx = aNode.x - bNode.x;
const dy = aNode.y - bNode.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < aNode.r + bNode.r)
return true;
}
}
return false;
}
/**
* Check if a round node collides with a square node
* @param a - the round node
* @param b - the square node
* @returns true if the nodes collide
*/
#collidesRoundSquare(a, b) {
// https://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection
for (const node of a.nodes) {
const dx = node.x - Math.max(b.minX, Math.min(node.x, b.maxX));
const dy = node.y - Math.max(b.minY, Math.min(node.y, b.maxY));
if (dx * dx + dy * dy < node.r * node.r)
return true;
}
return false;
}
/**
* Check if two square nodes collide
* @param a - the first square node
* @param b - the second square node
* @returns true if the nodes collide
*/
#collidesSquareSquare(a, b) {
return (a.id !== b.id && a.minX < b.maxX && a.maxX > b.minX && a.minY < b.maxY && a.maxY > b.minY);
}
}