diff --git a/html/images/space.svg b/html/images/space.svg
index dfb353a..e8ed1ff 100644
--- a/html/images/space.svg
+++ b/html/images/space.svg
@@ -59,7 +59,7 @@
-
+
@@ -156,6 +156,7 @@
function updateTriangles([positionX, positionY]) {
const delim = ' ';
const className = 'clockwise-orientation';
+ const visible = [];
triangles.forEach(t => {
const attr = t.getAttribute('points').split(delim);
@@ -174,11 +175,14 @@
}
t.classList[cwOrientation ? "add" : "remove"](className);
+ if (cwOrientation) visible.push(t);
// i think i can also discard obtuse triangles?
// if all the triangles are obtuse, i only need to check the nearest corner for a collision
// otherwise, i need to check only the acute triangles
});
+
+ return visible;
}
const lines = lineContainer.querySelectorAll('line');
@@ -286,6 +290,10 @@
animate(timestamp);
}
+ function distance(x1, y1, x2, y2) {
+ return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
+ }
+
function animate(timestamp) {
const delta = timestamp - zero;
const elapsed = timestamp - previous;
@@ -294,11 +302,11 @@
if (delta >= 1000) {
fps.innerText = frameCount;
- info.innerText = `velocity ${velocity}\n`
- + 'bullets\nx\ty\tvx\tvy\n'
- + bullets.map(b => {
- return `${b.x.toFixed(2)}\t${b.y.toFixed(2)}\t${b.vx.toFixed(2)}\t${b.vy.toFixed(2)}`;
- }).join("\n");
+ // info.innerText = `velocity ${velocity}\n`
+ // + 'bullets\nx\ty\tvx\tvy\n'
+ // + bullets.map(b => {
+ // return `${b.x.toFixed(2)}\t${b.y.toFixed(2)}\t${b.vx.toFixed(2)}\t${b.vy.toFixed(2)}`;
+ // }).join("\n");
zero = timestamp;
frameCount = 0;
@@ -306,6 +314,7 @@
frameCount++;
}
+
let degrees = getRotate(gun);
if (rotate > 0) gun.style.transform = `rotate(${(+degrees + rotationSpeed * elapsed) % 360}deg)`;
@@ -338,7 +347,26 @@
updateBullets(elapsed);
// updateLines(position);
- updateTriangles(position);
+ const visibleTriangles = updateTriangles(position);
+
+ // 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');
// can do this after side collision detection
// const ts = updateTriangles(position);
@@ -359,7 +387,25 @@
return shipBody.isPointInFill(cornerPt);
});
- wall.setAttribute('fill', cornerCollision ? 'red' : 'black');
+ const PI = Math.PI / 2;
+ 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 < PI && beta < PI;
+
+ return acute ? [...acc, hc] : acc;
+ }, []).some(h => h <= shipRadius);
+
+ wall.setAttribute('fill', cornerCollision || sideCollision ? 'red' : 'black');
hitbox.style.transform = `translate(${positionX}px, ${positionY}px)`;
// if (+y < 200)