Refactor edge collision detect function

This commit is contained in:
2026-01-05 09:22:36 -08:00
parent d9ab0fa1fd
commit 1de687b3f1

View File

@@ -656,18 +656,36 @@
return Object.is(slope(edge), +0);
}
function detectEdgeCollision([xc, yc], { xa, ya, xb, yb }, shipRadius) {
const da = distance(xa, ya, xc, yc);
const db = distance(xb, yb, xc, yc);
// TODO: calculate this one ahead of time
const dc = distance(xa, ya, xb, yb);
function detectEdgeCollision([xc, yc], [x, y], radius) {
return ({ edge, wall }) => {
if (xc === x && yc === y) return;
// 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));
const { xa, ya, xb, yb } = edge;
const rise = yb - ya;
const run = xb - xa;
const length = distance(xa, ya, xb, yb);
return +hc.toFixed(2) <= shipRadius;
const riol = rise / length * radius;
const ruol = run / length * radius;
const positionSeg = { xa: x, ya: y, xb: xc, yb: yc };
const edgeSeg = { xa: xa + riol, ya: ya - ruol, xb: xb + riol, yb: yb - ruol};
const { xa: x1, ya: y1, xb: x2, yb: y2 } = positionSeg;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = edgeSeg;
// 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);
const roundedS = +s.toFixed(2);
// console.log("edgeSeg", edgeSeg);
// console.log("s", roundedS, "t", roundedT);
return roundedS >= 0 && roundedS <= 1 && roundedT >= 0 && roundedT <= 1;
};
}
function detectCornerCollision([xc, yc], [x, y], radius) {
@@ -915,61 +933,34 @@
});
// console.log("edges facing ship", efs);
const positionSeg = { xa: x, ya: y, xb: xc, yb: yc };
// const positionSeg = { xa: x, ya: y, xb: xc, yb: yc };
console.log("positionSeg", positionSeg);
// console.log("positionSeg", positionSeg);
const edgeCollision = efs.find(({ edge, wall }) => {
const { xa, ya, xb, yb } = edge;
if (xc === x && yc === y) return;
const edgeColl = efs.find(detectEdgeCollision([xc, yc], [x, y], shipRadius));
const rise = yb - ya;
const run = xb - xa;
const length = distance(xa, ya, xb, yb);
const riol = rise / length * shipRadius;
const ruol = run / length * shipRadius;
const edgeSeg = { xa: xa + riol, ya: ya - ruol, xb: xb + riol, yb: yb - ruol};
const { xa: x1, ya: y1, xb: x2, yb: y2 } = positionSeg;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = edgeSeg;
// 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);
const roundedS = +s.toFixed(2);
console.log("edgeSeg", edgeSeg);
console.log("s", roundedS, "t", roundedT);
return roundedS >= 0 && roundedS <= 1 && roundedT >= 0 && roundedT <= 1;
});
efs.forEach(({ edge, wall }) => {
const { xa, ya, xb, yb } = edge;
const sl = slope(edge);
if (sl === Infinity) {
drawLine(xa + shipRadius, ya, xb + shipRadius, yb);
} else if (sl === -Infinity) {
drawLine(xa - shipRadius, ya, xb - shipRadius, yb);
} else if (Object.is(sl, -0)) {
drawLine(xa, ya + shipRadius, xb, yb + shipRadius);
} else if (sl === 0) {
drawLine(xa, ya - shipRadius, xb, yb - shipRadius);
} else {
const rise = yb - ya;
const run = xb - xa;
const length = distance(xa, ya, xb, yb)
const riol = rise / length * shipRadius;
const ruol = run / length * shipRadius;
drawLine(xa + riol, ya - ruol, xb + riol, yb - ruol);
}
});
// efs.forEach(({ edge, wall }) => {
// const { xa, ya, xb, yb } = edge;
// const sl = slope(edge);
// if (sl === Infinity) {
// drawLine(xa + shipRadius, ya, xb + shipRadius, yb);
// } else if (sl === -Infinity) {
// drawLine(xa - shipRadius, ya, xb - shipRadius, yb);
// } else if (Object.is(sl, -0)) {
// drawLine(xa, ya + shipRadius, xb, yb + shipRadius);
// } else if (sl === 0) {
// drawLine(xa, ya - shipRadius, xb, yb - shipRadius);
// } else {
// const rise = yb - ya;
// const run = xb - xa;
// const length = distance(xa, ya, xb, yb)
//
// const riol = rise / length * shipRadius;
// const ruol = run / length * shipRadius;
//
// drawLine(xa + riol, ya - ruol, xb + riol, yb - ruol);
// }
// });
// corners ahead of ship
const fCollC = getForwardCollisionCorners(ws, { x, y }, s.velocity);
@@ -983,24 +974,7 @@
const cornerColl = cwcd.find(detectCornerCollision([xc, yc], [x, y], shipRadius));
// const edgeColl = collE.find(({ edge, wall }) => {
// const { xa, ya, xb, yb } = edge;
// const da = distance(xa, ya, xc, yc);
// const db = distance(xb, yb, xc, yc);
// // TODO: calculate this one ahead of time
// 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));
// console.log("hc", hc);
//
// return +hc.toFixed(2) <= shipRadius;
// });
// s.collision = cornerColl || edgeCollision;
s.collision = edgeCollision || cornerColl;
s.collision = edgeColl || cornerColl;
if (s.collision) console.log("COLLISION", s.collision);

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 43 KiB