Move collision detection code into its own function

This commit is contained in:
2025-12-20 08:40:41 -08:00
parent 1f782f75aa
commit 50a20982a4

View File

@@ -314,6 +314,44 @@
}); });
} }
function detectCollision(points, visibleTriangles) {
const cornerCollision = points.some(([x, y]) => {
cornerPt.x = x - positionX;
cornerPt.y = y - positionY;
return shipBody.isPointInFill(cornerPt);
});
const shipRadius = 5;
const sideCollision = [...visibleTriangles].reduce((acc, t) => {
const [[ax, ay], [bx, by], [shipx, shipy]] =
t.getAttribute('points').split(' ').map(n => n.split(',').map(n => +n));
const da = distance(ax, ay, shipx, shipy);
const db = distance(bx, by, shipx, shipy);
// TODO: calculate this one ahead of time
const dc = distance(ax, ay, bx, by);
// https://en.wikipedia.org/wiki/Altitude_(triangle)#Altitude_in_terms_of_the_sides
// Find altitude of side c (the base)
const s = (1 / 2) * (da + db + dc);
const hc = (2 / dc) * Math.sqrt(s * (s - da) * (s - db) * (s - dc));
// https://en.wikipedia.org/wiki/Law_of_cosines
// Solve for angles alpha and beta with inverse cosine (arccosine) function
const alpha = Math.acos((db**2 + dc**2 - da**2) / (2 * db * dc));
const beta = Math.acos((da**2 + dc**2 - db**2) / (2 * da * dc));
// Is acute if both angles are < 90 degrees
// TODO: what about right triangles?
const isAcute = alpha < halfPi && beta < halfPi;
return isAcute ? [...acc, hc] : acc;
}, []).some(h => h <= shipRadius);
return cornerCollision || sideCollision;
}
requestAnimationFrame(firstFrame); requestAnimationFrame(firstFrame);
let start; let start;
@@ -408,65 +446,12 @@
drawEdges(trianglePts); drawEdges(trianglePts);
} }
// info.innerText = [...visibleTriangles].map(t => { const collision = detectCollision(points, visibleTriangles);
// const [[ax, ay], [bx, by], [shipx, shipy]] =
// t.getAttribute('points').split(' ').map(n => n.split(',').map(n => +n));
//
// const da = distance(ax, ay, shipx, shipy);
// const db = distance(bx, by, shipx, shipy);
// const dc = distance(ax, ay, bx, by);
// const s = (1 / 2) * (da + db + dc);
// const hc = (2 / dc) * Math.sqrt(s * (s - da) * (s - db) * (s - dc));
//
// const alpha = Math.acos((db**2 + dc**2 - da**2) / (2 * db * dc));
// const beta = Math.acos((da**2 + dc**2 - db**2) / (2 * da * dc));
//
// const PI = Math.PI / 2;
// const acute = alpha < PI && beta < PI;
//
// return `${da.toFixed(2)} ${db.toFixed(2)} ${dc.toFixed(2)} ${hc.toFixed(2)} ${alpha.toFixed(2)} ${beta.toFixed(2)}`;
// }).join('\n');
// can do this after side collision detection wall.setAttribute('fill', collision ? 'red' : 'black');
// const ts = updateTriangles(position);
// const corners = ts.reduce((acc, t) => {
// const [a, b,] = t.getAttribute('points').split(' ');
// // return p.map(t => t.split(','));
// // acc.push(a);
// // acc.push(b);
// return [a, b, ...acc];
// }, []);
//
// const uniqueCorners = [...new Set(corners)].map(n => n.split(',').map(n => +n));
const cornerCollision = points.some(([x, y]) => {
cornerPt.x = x - positionX;
cornerPt.y = y - positionY;
return shipBody.isPointInFill(cornerPt);
});
const shipRadius = 5;
const sideCollision = [...visibleTriangles].reduce((acc, t) => {
const [[ax, ay], [bx, by], [shipx, shipy]] =
t.getAttribute('points').split(' ').map(n => n.split(',').map(n => +n));
const da = distance(ax, ay, shipx, shipy);
const db = distance(bx, by, shipx, shipy);
const dc = distance(ax, ay, bx, by);
const s = (1 / 2) * (da + db + dc);
const hc = (2 / dc) * Math.sqrt(s * (s - da) * (s - db) * (s - dc));
const alpha = Math.acos((db**2 + dc**2 - da**2) / (2 * db * dc));
const beta = Math.acos((da**2 + dc**2 - db**2) / (2 * da * dc));
const acute = alpha < halfPi && beta < halfPi;
return acute ? [...acc, hc] : acc;
}, []).some(h => h <= shipRadius);
wall.setAttribute('fill', cornerCollision || sideCollision ? 'red' : 'black');
hitbox.style.transform = `translate(${positionX}px, ${positionY}px)`; hitbox.style.transform = `translate(${positionX}px, ${positionY}px)`;
if (cornerCollision || sideCollision) { if (collision) {
// restart game // restart game
zeroForTimer = timestamp; zeroForTimer = timestamp;
restart = true; restart = true;

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB