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)