Remove unused duplicate functions

This commit is contained in:
2026-02-04 13:49:12 -08:00
parent d89909e7bf
commit 424cb0f150

View File

@@ -198,17 +198,17 @@
<br/> <br/>
<span id="velocity" xmlns="http://www.w3.org/1999/xhtml">-,-</span> x,y velocity <span id="velocity" xmlns="http://www.w3.org/1999/xhtml">-,-</span> x,y velocity
</div> </div>
<ul xmlns="http://www.w3.org/1999/xhtml"> <!-- <ul xmlns="http://www.w3.org/1999/xhtml"> -->
<li xmlns="http://www.w3.org/1999/xhtml">bounce from collisions</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">bounce from collisions</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">fall off screen after crash</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">fall off screen after crash</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">make ship a helicopter</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">make ship a helicopter</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">use paths for walls</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">use paths for walls</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">stop reading data from elements</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">stop reading data from elements</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">limited fuel</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">limited fuel</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">additional cannon firing modes</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">additional cannon firing modes</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">keep ship position at 0,0 actual</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">keep ship position at 0,0 actual</li> -->
<li xmlns="http://www.w3.org/1999/xhtml">only start on movement not just any keypress</li> <!-- <li xmlns="http://www.w3.org/1999/xhtml">only start on movement not just any keypress</li> -->
</ul> <!-- </ul> -->
<pre id="debug" xmlns="http://www.w3.org/1999/xhtml"></pre> <pre id="debug" xmlns="http://www.w3.org/1999/xhtml"></pre>
<div id="pointer" xmlns="http://www.w3.org/1999/xhtml"> <div id="pointer" xmlns="http://www.w3.org/1999/xhtml">
x: <span class="x" xmlns="http://www.w3.org/1999/xhtml">-</span>, x: <span class="x" xmlns="http://www.w3.org/1999/xhtml">-</span>,
@@ -1090,14 +1090,6 @@ function init() {
time.innerText = "0"; time.innerText = "0";
} }
// const b = map.edges.map(({ edge }) => getEdgeCollisionBoundary(edge, shipRadius));
// b.forEach(b => drawLine(b.xa, b.ya, b.xb, b.yb, "orange"));
function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
function drawTriangles(container, walls, [positionX, positionY]) { function drawTriangles(container, walls, [positionX, positionY]) {
walls.forEach(pts => walls.forEach(pts =>
pts.forEach(([[x1, y1], [x2, y2]]) => { pts.forEach(([[x1, y1], [x2, y2]]) => {
@@ -1109,93 +1101,6 @@ function drawTriangles(container, walls, [positionX, positionY]) {
); );
} }
// Triangle has a clockwise orientation
function isClockwise([xa, ya], [xb, yb], [xc, yc]) {
// https://en.wikipedia.org/wiki/Curve_orientation#Practical_considerations
// Determinant for a convex polygon
const det = (+xb - +xa) * (+yc - +ya) - (+xc - +xa) * (+yb - +ya);
return det < 0;
}
function isAcute([xa, ya], [xb, yb], [xc, yc]) {
const da = distance(xa, ya, xc, yc);
const db = distance(xb, yb, xc, yc);
const dc = distance(xa, ya, xb, yb);
// https://en.wikipedia.org/wiki/Law_of_cosines
// Solve for angles alpha and beta with inverse cosine (arccosine)
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));
return alpha < halfPi && beta < halfPi;
}
function getForwardEdges(edges, { x, y }) {
return edges.filter(({ edge: { xa, ya, xb, yb } }) =>
isClockwise([xa, ya], [xb, yb], [x, y]) && isAcute([xa, ya], [xb, yb], [x, y]));
}
function getForwardCorners(corners, position, velocity) {
const { x: x1, y: y1 } = position;
const { x: x2, y: y2 } = velocity;
const { x: vx, y: vy } = velocity;
let perppts = {};
if (vx === 0 && vy === 0) {
// none
} else if (vx === 0 && vy > 0) {
perppts = { a: { x: x1 - 1, y: y1 }, b: { x: x1 + 1, y: y1 }};
} else if (vx === 0 && vy < 0) {
perppts = { a: { x: x1 + 1, y: y1 }, b: { x: x1 - 1, y: y1 }};
} else if (vy === 0 && vx > 0) {
perppts = { a: { x: x1, y: y1 + 1 }, b: { x: x1, y: y1 - 1 }};
} else if (vy === 0 && vx < 0) {
perppts = { a: { x: x1, y: y1 - 1 }, b: { x: x1, y: y1 + 1 }};
} else if (vy > 0 && vx > 0) {
const vslope = vy / vx;
const pslope = 1 / -vslope;
// Point-slope line equation
const pya = pslope * (x1 - 1) - pslope * x1 + y1;
const pyb = pslope * (x1 + 1) - pslope * x1 + y1;
perppts = { a: { x: x1 - 1, y: pya }, b: { x: x1 + 1, y: pyb }};
} else if (vy > 0 && vx < 0) {
const vslope = vy / vx;
const pslope = 1 / -vslope;
const pya = pslope * (x1 - 1) - pslope * x1 + y1;
const pyb = pslope * (x1 + 1) - pslope * x1 + y1;
perppts = { a: { x: x1 - 1, y: pya }, b: { x: x1 + 1, y: pyb }};
} else if (vy < 0 && vx > 0) {
const vslope = vy / vx;
const pslope = 1 / -vslope;
const pya = pslope * (x1 + 1) - pslope * x1 + y1;
const pyb = pslope * (x1 - 1) - pslope * x1 + y1;
perppts = { a: { x: x1 + 1, y: pya }, b: { x: x1 - 1, y: pyb }};
} else if (vy < 0 && vx < 0) {
const vslope = vy / vx;
const pslope = 1 / -vslope;
const pya = pslope * (x1 + 1) - pslope * x1 + y1;
const pyb = pslope * (x1 - 1) - pslope * x1 + y1;
perppts = { a: { x: x1 + 1, y: pya }, b: { x: x1 - 1, y: pyb }};
} else {
//
}
const { a, b } = perppts;
// if (a && b) drawLine(a.x, a.y, b.x, b.y);
return corners.filter(({ corner: c }) => {
if (!a || !b) return;
const det = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
return det > 0;
});
}
function updateTriangles([positionX, positionY]) { function updateTriangles([positionX, positionY]) {
const delim = ' '; const delim = ' ';
const className = 'clockwise-orientation'; const className = 'clockwise-orientation';
@@ -1322,25 +1227,6 @@ function fireBullet(position, degrees) {
setTimeout(() => appended.classList.add('fade'), 1000); setTimeout(() => appended.classList.add('fade'), 1000);
} }
function perpIntxn(baseSlope, xa, ya, xc, yc) {
let isx, isy;
// base is vertical
if (baseSlope === -Infinity || baseSlope === Infinity) {
isx = xa;
isy = yc;
} else if (baseSlope === 0) { // base is horizontal
isx = xc;
isy = ya;
} else {
const altitudeSlope = 1 / -baseSlope;
isx = (-altitudeSlope * xc + yc + baseSlope * xa - ya) / (baseSlope - altitudeSlope);
isy = altitudeSlope * isx - altitudeSlope * xc + yc;
}
return { x: isx, y: isy };
}
function drawLine(xa, ya, xb, yb, color = "black") { function drawLine(xa, ya, xb, yb, color = "black") {
const el = document.createElementNS(namespaceURIsvg, 'line'); const el = document.createElementNS(namespaceURIsvg, 'line');
el.setAttribute('x1', xa); el.setAttribute('x1', xa);
@@ -1369,142 +1255,11 @@ function drawCircle(cx, cy, color = "black", r = 1) {
return el; return el;
} }
function slope({ xa, ya, xb, yb }) {
return (yb - ya) / (xb - xa);
}
function isLandable(edge) { function isLandable(edge) {
return edge.xa < edge.xb && edge.ya === edge.yb; return edge.xa < edge.xb && edge.ya === edge.yb;
// return Object.is(slope(edge), +0); // return Object.is(slope(edge), +0);
} }
function getEdgeCollisionBoundary(edge, dist) {
const { xa, ya, xb, yb } = edge;
const length = distance(xa, ya, xb, yb);
const rise = yb - ya;
const run = xb - xa;
const riol = rise / length * dist;
const ruol = run / length * dist;
return { xa: xa + riol, ya: ya - ruol, xb: xb + riol, yb: yb - ruol};
}
function detectEdgeCollision([xc, yc], [x, y], radius, gearDown) {
return (collision) => {
if (xc === x && yc === y) return;
const { edge, wall } = collision;
const dist = edge.xa < edge.xb && edge.ya === edge.yb && gearDown ? radius + 1.5 : radius;
const edgeSeg = getEdgeCollisionBoundary(edge, dist);
const positionSeg = { xa: x, ya: y, xb: xc, yb: yc };
const { xa: x1, ya: y1, xb: x2, yb: y2 } = positionSeg;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = edgeSeg;
// const { xa: x3, ya: y3, xb: x4, yb: y4 } = edge;
// https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments
// https://en.wikipedia.org/wiki/Cramer%27s_rule#Explicit_formulas_for_small_systems
// const denom = +((x2-x1)*(y4-y3)-(x4-x3)*(y2-y1)).toPrecision(13);
const x21 = +(x2-x1).toPrecision(13);
const y43 = +(y4-y3).toPrecision(13);
const x43 = +(x4-x3).toPrecision(13);
const y21 = +(y2-y1).toPrecision(13);
const denom = +(x21*y43-x43*y21).toPrecision(13);
const x31 = +(x3-x1).toPrecision(13);
const y31 = +(y3-y1).toPrecision(13);
const s = +(+(x31*y43-x43*y31).toPrecision(13) / denom).toPrecision(13);
const t = +(-(x21*y31-x31*y21).toPrecision(13) / denom).toPrecision(13);
// const s = +(((x3-x1)*(y4-y3)-(x4-x3)*(y3-y1))/denom).toPrecision(13);
// const t = +(-((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1))/denom).toPrecision(13);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
const xs = (x1 + s * +(x2 - x1).toPrecision(13));
const ys = (y1 + s * +(y2 - y1).toPrecision(13));
collision.position = { x: +xs.toPrecision(13), y: +ys.toPrecision(13) };
return true;
}
// return roundedS >= 0 && roundedS <= 1 && roundedT >= 0 && roundedT <= 1;
return;
};
}
function detectCornerCollision([xc, yc], [x, y], radius) {
return c => {
if (xc === x && yc === y) return;
const d = distance(c.corner.x, c.corner.y, xc, yc);
if (d <= radius) return true;
const positionSeg = { xa: xc, ya: yc, xb: x, yb: y };
const posNormIntxn = perpIntxn(slope(positionSeg), x, y, c.corner.x, c.corner.y);
const cornerSeg = { xa: c.corner.x, ya: c.corner.y, xb: posNormIntxn.x, yb: posNormIntxn.y };
const { x: x0, y: y0 } = c.corner;
const { xa: x1, ya: y1, xb: x2, yb: y2 } = positionSeg;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = cornerSeg;
// https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments
// https://en.wikipedia.org/wiki/Cramer%27s_rule#Explicit_formulas_for_small_systems
const s = ((x3-x1)*(y4-y3)-(x4-x3)*(y3-y1))/((x2-x1)*(y4-y3)-(x4-x3)*(y2-y1));
const t = -((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1))/((x2-x1)*(y4-y3)-(x4-x3)*(y2-y1));
const roundedT = +t.toFixed(2);
if (s >= 0 && roundedT <= 1) {
const xs = (x1 + s * (x2 - x1));
const ys = (y1 + s * (y2 - y1));
const xt = (x3 + roundedT * (x4 - x3));
const yt = (y3 + roundedT * (y4 - y3));
// [xs, ys] and [xt, yt] should be equal ([xs, ys] === [xy, yt])
// (...or about equal, notwithstanding rounding errors)
const sCollisionPt = [xs, ys];
const tCollisionPt = [xt, yt];
// drawCircle(posNormIntxn.x, posNormIntxn.y, "red");
// drawCircle(...tCollisionPt, "blue");
}
return s >= 0 && roundedT <= 1;
};
}
function detectCollision(currentPos, intendedPos, velocity, radius, { edges, corners }, gearDown) {
const { x: xc, y: yc } = intendedPos;
const [x, y] = currentPos;
// edges oriented clockwise with ship
const fwdEdges = getForwardEdges(edges, { x, y })
const edgeColl = fwdEdges.find(detectEdgeCollision([xc, yc], [x, y], radius, gearDown));
if (edgeColl) return edgeColl;
// corners ahead of ship
const fwdCorners = getForwardCorners(corners, { x, y }, velocity);
const cornersInPath = fwdCorners.filter(withinCollisionDistance({ x, y }, velocity, radius));
const cornerColl = cornersInPath.find(detectCornerCollision([xc, yc], [x, y], radius));
if (cornerColl) return cornerColl;
}
function withinCollisionDistance({ x: x1, y: y1 }, { x: x2, y: y2 }, distance) {
const diffx = x2;
const diffy = y2;
const detv = x2 * y1 - y2 * x1;
const dv = Math.sqrt(diffy ** 2 + diffx ** 2);
const slopev = slope({ xa: x1, ya: y1, xb: x1 + x2, yb: y1 + y2 });
return ({ corner: { x: x0, y: y0 }}) => {
const velNormIntxn = perpIntxn(slopev, x1, y1, x0, y0);
const dx = Math.max(x0, velNormIntxn.x) - Math.min(x0, velNormIntxn.x);
const dy = Math.max(y0, velNormIntxn.y) - Math.min(y0, velNormIntxn.y);
const d = Math.sqrt(dy ** 2 + dx ** 2);
return d <= distance;
};
}
function cornerContactPosition(xc, yc, x, y, corner, cLength) { function cornerContactPosition(xc, yc, x, y, corner, cLength) {
const positionSeg = { xa: xc, ya: yc, xb: x, yb: y }; const positionSeg = { xa: xc, ya: yc, xb: x, yb: y };
const posNormIntxn = perpIntxn(slope(positionSeg), x, y, corner.x, corner.y); const posNormIntxn = perpIntxn(slope(positionSeg), x, y, corner.x, corner.y);
@@ -1628,7 +1383,7 @@ function updateShip(s, elapsed) {
s.degrees = degrees + dDelta; s.degrees = degrees + dDelta;
current = s.collision; current = s.collision;
s.collision = detectCollision([px, py], p, s.velocity, s.radius, map, s.gearDown); // s.collision = detectCollision([px, py], p, s.velocity, s.radius, map, s.gearDown);
// if (!current && s.collision) console.log("COLLISION", s.collision); // if (!current && s.collision) console.log("COLLISION", s.collision);
legs.style.display = s.gearDown ? "initial" : "none"; legs.style.display = s.gearDown ? "initial" : "none";

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 57 KiB