diff --git a/html/images/space.svg b/html/images/space.svg
index 0071be3..c1f2192 100644
--- a/html/images/space.svg
+++ b/html/images/space.svg
@@ -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);
let start;
@@ -408,65 +446,12 @@
drawEdges(trianglePts);
}
- // info.innerText = [...visibleTriangles].map(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 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');
+ const collision = detectCollision(points, visibleTriangles);
- // can do this after side collision detection
- // 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');
+ wall.setAttribute('fill', collision ? 'red' : 'black');
hitbox.style.transform = `translate(${positionX}px, ${positionY}px)`;
- if (cornerCollision || sideCollision) {
+ if (collision) {
// restart game
zeroForTimer = timestamp;
restart = true;