diff --git a/html/images/space.svg b/html/images/space.svg index 1a73354..8e893eb 100644 --- a/html/images/space.svg +++ b/html/images/space.svg @@ -91,8 +91,8 @@ - - + + @@ -147,7 +147,7 @@ const triangleContainer = document.querySelector('#triangles'); 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; function drawEdges(lpts) { @@ -167,7 +167,7 @@ }); } - drawEdges(trianglePts); + drawEdges(edgePts); function drawTriangles(container, pts, [positionX, positionY]) { pts.forEach(([[x1, y1], [x2, y2]]) => { @@ -178,7 +178,7 @@ }); } - drawTriangles(triangleContainer, trianglePts, position); + drawTriangles(triangleContainer, edgePts, position); const triangles = triangleContainer.querySelectorAll('polygon'); // Triangle has a clockwise orientation @@ -209,7 +209,7 @@ }, []); } - const collisionEdges = findEdges(trianglePts, position); + const collisionEdges = findEdges(edgePts, position); function updateTriangles([positionX, positionY]) { const delim = ' '; @@ -339,39 +339,29 @@ }); } - function detectCollision(points, visibleTriangles) { + function detectCollision(points, [xc, yc], edges) { const cornerCollision = points.some(([x, y]) => { - cornerPt.x = x - positionX; - cornerPt.y = y - positionY; + cornerPt.x = x - xc; + cornerPt.y = y - yc; 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 sideCollision = edges.reduce((acc, e) => { + const [[xa, ya], [xb, yb]] = e.split(' ').map(n => n.split(',').map(n => +n)); - const da = distance(ax, ay, shipx, shipy); - const db = distance(bx, by, shipx, shipy); + const da = distance(xa, ya, xc, yc); + const db = distance(xb, yb, xc, yc); // 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 // 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; + return [...acc, hc]; }, []).some(h => h <= shipRadius); return cornerCollision || sideCollision; @@ -409,6 +399,25 @@ 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 restart = false; function firstFrame(timestamp) { @@ -449,38 +458,15 @@ position = updateShip(elapsed); updateBullets(elapsed); - - 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(); - }); + updateEdges(position); if (restart) { restart = false; [...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'); if (collision) {