This commit is contained in:
2025-12-20 15:06:16 -08:00
parent f6974d43f4
commit 273ed43a51

View File

@@ -91,8 +91,8 @@
</g> </g>
</g> </g>
<polygon id="wall" points="20,20 40,20 40,40 20,40" /> <!-- <polygon id="wall" points="20,20 40,20 40,40 20,40" /> -->
<!-- <polygon id="wall" points="-10,-30 -10,-40 30,-50 60,-30 80,0 150,0 150,10 60,50 -10,40 -20,20 20,20 20,-20" /> --> <polygon id="wall" points="-10,-30 -10,-40 30,-50 60,-30 80,0 150,0 150,10 60,50 -10,40 -20,20 20,20 20,-20" />
<g id="triangles"></g> <g id="triangles"></g>
<g id="lines"></g> <g id="lines"></g>
@@ -147,7 +147,7 @@
const triangleContainer = document.querySelector('#triangles'); const triangleContainer = document.querySelector('#triangles');
const lineContainer = document.querySelector('#lines'); const lineContainer = document.querySelector('#lines');
const trianglePts = points.map((pt, i) => [pt, points[(i + 1) % points.length]]); const edgePts = points.map((pt, i) => [pt, points[(i + 1) % points.length]]);
const drawCollisionLines = false; const drawCollisionLines = false;
function drawEdges(lpts) { function drawEdges(lpts) {
@@ -167,7 +167,7 @@
}); });
} }
drawEdges(trianglePts); drawEdges(edgePts);
function drawTriangles(container, pts, [positionX, positionY]) { function drawTriangles(container, pts, [positionX, positionY]) {
pts.forEach(([[x1, y1], [x2, y2]]) => { pts.forEach(([[x1, y1], [x2, y2]]) => {
@@ -178,7 +178,7 @@
}); });
} }
drawTriangles(triangleContainer, trianglePts, position); drawTriangles(triangleContainer, edgePts, position);
const triangles = triangleContainer.querySelectorAll('polygon'); const triangles = triangleContainer.querySelectorAll('polygon');
// Triangle has a clockwise orientation // Triangle has a clockwise orientation
@@ -209,7 +209,7 @@
}, []); }, []);
} }
const collisionEdges = findEdges(trianglePts, position); const collisionEdges = findEdges(edgePts, position);
function updateTriangles([positionX, positionY]) { function updateTriangles([positionX, positionY]) {
const delim = ' '; const delim = ' ';
@@ -339,39 +339,29 @@
}); });
} }
function detectCollision(points, visibleTriangles) { function detectCollision(points, [xc, yc], edges) {
const cornerCollision = points.some(([x, y]) => { const cornerCollision = points.some(([x, y]) => {
cornerPt.x = x - positionX; cornerPt.x = x - xc;
cornerPt.y = y - positionY; cornerPt.y = y - yc;
return shipBody.isPointInFill(cornerPt); return shipBody.isPointInFill(cornerPt);
}); });
const shipRadius = 5; const shipRadius = 5;
const sideCollision = [...visibleTriangles].reduce((acc, t) => { const sideCollision = edges.reduce((acc, e) => {
const [[ax, ay], [bx, by], [shipx, shipy]] = const [[xa, ya], [xb, yb]] = e.split(' ').map(n => n.split(',').map(n => +n));
t.getAttribute('points').split(' ').map(n => n.split(',').map(n => +n));
const da = distance(ax, ay, shipx, shipy); const da = distance(xa, ya, xc, yc);
const db = distance(bx, by, shipx, shipy); const db = distance(xb, yb, xc, yc);
// TODO: calculate this one ahead of time // TODO: calculate this one ahead of time
const dc = distance(ax, ay, bx, by); const dc = distance(xa, ya, xb, yb);
// https://en.wikipedia.org/wiki/Altitude_(triangle)#Altitude_in_terms_of_the_sides // https://en.wikipedia.org/wiki/Altitude_(triangle)#Altitude_in_terms_of_the_sides
// Find altitude of side c (the base) // Find altitude of side c (the base)
const s = (1 / 2) * (da + db + dc); const s = (1 / 2) * (da + db + dc);
const hc = (2 / dc) * Math.sqrt(s * (s - da) * (s - db) * (s - dc)); const hc = (2 / dc) * Math.sqrt(s * (s - da) * (s - db) * (s - dc));
// https://en.wikipedia.org/wiki/Law_of_cosines return [...acc, hc];
// 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); }, []).some(h => h <= shipRadius);
return cornerCollision || sideCollision; return cornerCollision || sideCollision;
@@ -409,6 +399,25 @@
return position; return position;
} }
function updateEdges(position) {
const mappedEdges = findEdges(edgePts, position);
[...lineContainer.children].forEach(l => {
const x1 = l.getAttribute('x1');
const y1 = l.getAttribute('y1');
const x2 = l.getAttribute('x2');
const y2 = l.getAttribute('y2');
const edge = `${x1},${y1} ${x2},${y2}`;
if (mappedEdges.includes(edge))
if ([
lineContainer.childElementCount <= collisionEdges.length,
!collisionEdges.includes(edge)
].some(c => c))
l.remove();
});
}
let start; let start;
let restart = false; let restart = false;
function firstFrame(timestamp) { function firstFrame(timestamp) {
@@ -449,38 +458,15 @@
position = updateShip(elapsed); position = updateShip(elapsed);
updateBullets(elapsed); updateBullets(elapsed);
updateEdges(position);
const visibleTriangles = updateTriangles(position);
const visibleTrianglePoints = [...visibleTriangles].map(p => p.getAttribute("points"));
const mappedEdges = visibleTrianglePoints.map(vt => {
vt = vt.split(' ');
vt.pop();
return vt.join(' ');
});
[...lineContainer.children].forEach(l => {
const x1 = l.getAttribute('x1');
const y1 = l.getAttribute('y1');
const x2 = l.getAttribute('x2');
const y2 = l.getAttribute('y2');
const str = `${x1},${y1} ${x2},${y2}`;
if (mappedEdges.includes(str))
if ([
lineContainer.childElementCount <= collisionEdges.length,
!collisionEdges.includes(str)
].some(c => c))
l.remove();
});
if (restart) { if (restart) {
restart = false; restart = false;
[...lineContainer.children].forEach(c => c.remove());; [...lineContainer.children].forEach(c => c.remove());;
drawEdges(trianglePts); drawEdges(edgePts);
} }
const collision = detectCollision(points, visibleTriangles); const collision = detectCollision(points, position, findEdges(edgePts, position));
wall.setAttribute('fill', collision ? 'red' : 'black'); wall.setAttribute('fill', collision ? 'red' : 'black');
if (collision) { if (collision) {

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB