fix collision

This commit is contained in:
“chrisshank” 2024-12-07 00:41:35 -08:00
parent acc29c6c78
commit d3ea50b37a
2 changed files with 12 additions and 13 deletions

View File

@ -52,7 +52,7 @@
import { FolkShape } from '../src/standalone/folk-shape.ts'; import { FolkShape } from '../src/standalone/folk-shape.ts';
import { aabbHitDetection } from '../src/common/collision.ts'; import { aabbHitDetection } from '../src/common/collision.ts';
const shapes = Array.from(document.querySelectorAll('folk-shape')); const shapes = Array.from(document.querySelectorAll('folk-shape, p'));
const getBoundingBox = (el) => (el instanceof FolkShape ? el.getTransformDOMRect() : el.getBoundingClientRect()); const getBoundingBox = (el) => (el instanceof FolkShape ? el.getTransformDOMRect() : el.getBoundingClientRect());
@ -60,13 +60,13 @@
for (const shape of shapes) { for (const shape of shapes) {
if (shape === e.target) continue; if (shape === e.target) continue;
const hit = aabbHitDetection(getBoundingBox(shape), getBoundingBox(e.target)); const hit = aabbHitDetection(getBoundingBox(e.target), getBoundingBox(shape));
if (hit === null) continue; if (hit === null) continue;
if (shape instanceof FolkShape) { if (shape instanceof FolkShape) {
if (hit.delta.x !== 0) shape.x -= hit.delta.x; if (hit.delta.x !== 0) shape.x += hit.delta.x;
if (hit.delta.y !== 0) shape.y -= hit.delta.y; if (hit.delta.y !== 0) shape.y += hit.delta.y;
} else { } else {
if (hit.delta.x !== 0) e.preventX(); if (hit.delta.x !== 0) e.preventX();
if (hit.delta.y !== 0) e.preventY(); if (hit.delta.y !== 0) e.preventY();

View File

@ -15,39 +15,38 @@ export class Hit {
} }
const center = (rect: DOMRectReadOnly) => ({ const center = (rect: DOMRectReadOnly) => ({
width: rect.width / 2,
height: rect.height / 2,
x: rect.x + rect.width / 2, x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2, y: rect.y + rect.height / 2,
}); });
/** Test collisions of axis-aligned bounding boxes. */
export function aabbHitDetection(rect1: DOMRectReadOnly, rect2: DOMRectReadOnly): Hit | null { export function aabbHitDetection(rect1: DOMRectReadOnly, rect2: DOMRectReadOnly): Hit | null {
const center1 = center(rect1); const center1 = center(rect1);
const center2 = center(rect2); const center2 = center(rect2);
const dx = center1.x - center2.x; const dx = center2.x - center1.x;
const px = (rect2.width + rect1.width) / 2 - Math.abs(dx); const px = center2.width + center1.width - Math.abs(dx);
if (px <= 0) return null; if (px <= 0) return null;
const dy = center2.y - center1.y; const dy = center2.y - center1.y;
const py = (rect2.height + rect1.height) / 2 - Math.abs(dy); const py = center2.height + center1.height - Math.abs(dy);
if (py <= 0) return null; if (py <= 0) return null;
const hit = new Hit(); const hit = new Hit();
if (px < py) { if (px < py) {
const sx = sign(dx); const sx = sign(dx);
hit.delta.x = px * sx; hit.delta.x = px * sx;
hit.normal.x = sx; hit.normal.x = sx;
hit.pos.x = center1.x + (rect1.width / 2) * sx; hit.pos.x = center1.x + center1.width * sx;
hit.pos.y = center2.y; hit.pos.y = center2.y;
} else { } else {
const sy = sign(dy); const sy = sign(dy);
hit.delta.y = py * sy; hit.delta.y = py * sy;
hit.normal.y = sy; hit.normal.y = sy;
hit.pos.x = rect2.x; hit.pos.x = center2.x;
hit.pos.y = center2.y + (rect1.height / 2) * sy; hit.pos.y = center1.y + center1.height * sy;
} }
return hit; return hit;
} }