Corner collisions

This commit is contained in:
2026-01-03 12:03:59 -08:00
parent d45575db7c
commit 0868c953a3

View File

@@ -189,16 +189,18 @@
let acceleration; // meters per second per second let acceleration; // meters per second per second
let rotate = 0; let rotate = 0;
let mult = 20; let mult = 1000;
const s = { const s = {
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
velocity: { x: 5, y: -10 },
// velocity: { x: 5*mult, y: -10*mult },
// velocity: { x: 0, y: -10 }, // velocity: { x: 0, y: -10 },
// velocity: { x: 10, y: 10 }, // velocity: { x: 10, y: 10 },
// velocity: { x: -10, y: -10 }, // velocity: { x: -10, y: -10 },
// velocity: { x: 10, y: -10 }, // velocity: { x: 10, y: -10 },
// velocity: { x: -10, y: 10 }, // velocity: { x: -10, y: 10 },
velocity: { x: -10, y: 0 }, // velocity: { x: -10, y: 0 },
// velocity: { x: 10, y: 0 }, // velocity: { x: 10, y: 0 },
// velocity: { x: 0, y: -5000 }, // velocity: { x: 0, y: -5000 },
@@ -266,6 +268,13 @@
}; };
}); });
const mcs = ws.reduce(
(acc, wall) => [...acc, ...wall.corners.map(c => ({ corner: c, node: wall }))],
[]
);
console.log("corners on map", mcs);
const edgeszz = [...walls].map(wall => { const edgeszz = [...walls].map(wall => {
const es = wall.getAttribute('points').split(' ').map((coords, i, arr) => { const es = wall.getAttribute('points').split(' ').map((coords, i, arr) => {
const [x, y] = coords.split(','); const [x, y] = coords.split(',');
@@ -406,15 +415,10 @@
function getForwardCollisionCorners(walls, position, velocity) { function getForwardCollisionCorners(walls, position, velocity) {
const { x: x1, y: y1 } = position; const { x: x1, y: y1 } = position;
const { x: x2, y: y2 } = velocity; const { x: x2, y: y2 } = velocity;
// const a = { x: -100, y: 0 };
// const b = { x: 100, y: 0 };
// console.log("VELOCITY", velocity);
const { x: vx, y: vy } = velocity; const { x: vx, y: vy } = velocity;
// console.log("velocity", velocity, "position", position); let perppts = {};
let perppts;
if (vx === 0 && vy === 0) { if (vx === 0 && vy === 0) {
// none // none
@@ -460,15 +464,15 @@
} }
const { a, b } = perppts; const { a, b } = perppts;
drawLine(a.x, a.y, b.x, b.y); if (a && b) drawLine(a.x, a.y, b.x, b.y);
return walls.reduce((acc, w) => { return walls.reduce((acc, w) => {
const filtered = w.corners.filter(c => { const filtered = a && b ? w.corners.filter(c => {
// https://stackoverflow.com/a/1560510 // https://stackoverflow.com/a/1560510
const det = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); const det = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
return det > 0; return det > 0;
}); }).map(c => ({ corner: c, node: w.node })) : [];
return [...acc, ...filtered]; return [...acc, ...filtered];
}, []); }, []);
@@ -661,6 +665,62 @@
return actualCorner; return actualCorner;
} }
function withinCollisionDistance({ x: x1, y: y1 }, { x: x2, y: y2 }) {
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 }, node: n }) => {
const velNormIntxn = perpIntxn(slopev, x1, y1, x0, y0);
// console.log("x0", x0, "y0", y0, "velNormIntxn", velNormIntxn);
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);
// console.log("dddddddddddd", d);
return d <= shipRadius;
// return true;
};
}
function lineSegIntxn(point, seg1, seg2) {
const { x: x0, y: y0 } = point;
const { xa: x1, ya: y1, xb: x2, yb: y2 } = seg1;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = seg2;
// console.log(`s = (${x3-x1} + t${x4-x3}) / ${x2-x1}`);
// console.log(`s = (${x3-x1} + t${x4-x3}) / ${x2-x1}`);
// console.log(`${y2-y1} * (${x3-x1} + t${x4-x3}) / ${x2-x1} - t${y4-y3} = ${y3-y1}`);
// console.log(`${y2-y1} * (${x3-x1} + t${x4-x3}) / ${x2-x1} - t${y4-y3} = ${y3-y1}`);
//
// console.log(`${x2-x1}s - t${x4-x3} = ${x3-x1}`);
// console.log(`${y2-y1}s - t${y4-y3} = ${y3-y1}`);
// https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments
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 x = x1 + s * (x2-x1);
// const y = y3 + t * (y4-y3);
const xs = x1+s*(x2-x1);
const ys = y1+s*(y2-y1);
const xt = x3+t*(x4-x3);
const yt = y3+t*(y4-y3);
// console.log("point", point, "seg1", seg1, "seg2", seg2);
// console.log("s", s, "t", t);
// console.log("xs", xs, "ys", ys, "xt", xt, "yt", yt);
if (s >= 0 && t <= 1) {
console.log("CORNER COLLISION", "point", point, "position segment", seg1);
}
// console.log(`x1 ${x1} y1 ${y1} x2 ${x2} y2 ${y2} x3 ${x3} y3 ${y3} x4 ${x4} y4 ${y4} x0 ${x0} y0 ${y0}`);
// console.log("point", point, "seg1", seg1, "seg2", seg2, "s", s, "t", t);
}
function cornerCollisionPosition({ x: x1, y: y1 }, { x: x2, y: y2 }) { function cornerCollisionPosition({ x: x1, y: y1 }, { x: x2, y: y2 }) {
// todo1: i only want the collisions ahead, not behind // todo1: i only want the collisions ahead, not behind
// todo2: how do we tell if we've passed the collision point already? // todo2: how do we tell if we've passed the collision point already?
@@ -674,7 +734,9 @@
return ({ corner: { x: x0, y: y0 }, node: n }) => { return ({ corner: { x: x0, y: y0 }, node: n }) => {
const velNormIntxn = perpIntxn(slopev, x1, y1, x0, y0); const velNormIntxn = perpIntxn(slopev, x1, y1, x0, y0);
const d = Math.abs(diffy * x0 - diffx * y0 + detv) / dv; const d = Math.abs(diffy * x0 - diffx * y0 + detv) / dv;
const b = Math.sqrt(shipRadius ** 2 - d ** 2); // console.log("dddddddddddd", d);
// const b = Math.sqrt(shipRadius ** 2 - d ** 2);
const b = Math.sqrt(Math.max(shipRadius, d) ** 2 - Math.min(shipRadius, d) ** 2);
const cl = document.createElementNS(namespaceURIsvg, 'line'); const cl = document.createElementNS(namespaceURIsvg, 'line');
cl.setAttribute('x1', velNormIntxn.x); cl.setAttribute('x1', velNormIntxn.x);
@@ -756,36 +818,83 @@
const changeY = 0.001 * elapsed * velocityY; const changeY = 0.001 * elapsed * velocityY;
let { x, y } = s.position; let { x, y } = s.position;
// console.log("current position", x, y); console.log("current position", x, y);
// console.log("elapsed", elapsed, "changeX", changeX, "changeY", changeY); // console.log("elapsed", elapsed, "changeX", changeX, "changeY", changeY);
// let position = [positionX, positionY] = restart ? [0, 0] : wrapPos(changeX + x, changeY + y); // let position = [positionX, positionY] = restart ? [0, 0] : wrapPos(changeX + x, changeY + y);
let position = [positionX, positionY] = [changeX + x, changeY + y]; let position = [positionX, positionY] = [changeX + x, changeY + y];
let [xc, yc] = position; let [xc, yc] = position;
// console.log("future position", xc, yc); console.log("future position", xc, yc);
const collE = getCollisionEdges(edgeszz, position); const collE = getCollisionEdges(edgeszz, position);
// console.log("position", { x, y }, "velocity", s.velocity); // console.log("position", { x, y }, "velocity", s.velocity);
const collC = getCollisionCorners(ws, { x, y }, s.velocity); // const collC = getCollisionCorners(ws, { x, y }, s.velocity);
const fCollC = getForwardCollisionCorners(ws, { x, y }, s.velocity); const fCollC = getForwardCollisionCorners(ws, { x, y }, s.velocity);
// console.log("corners ahead of ship", fCollC);
cwcd = fCollC.filter(withinCollisionDistance({ x, y }, s.velocity));
// console.log("corners on collision path", cwcd);
// cwcd.forEach(c => {
// const positionSeg = { xa: x, ya: y, xb: xc, yb: yc };
// const positionSeg = { xa: xc, ya: yc, xb: x, yb: y };
// const slopeps = slope(positionSeg);
// const posNormIntxn = perpIntxn(slopeps, x, y, c.corner.x, c.corner.y);
// const cornerSeg = { xa: c.corner.x, ya: c.corner.y, xb: posNormIntxn.x, yb: posNormIntxn.y };
//
// lineSegIntxn(c.corner, positionSeg, cornerSeg);
// });
// console.log("collision corners", collC); // console.log("collision corners", collC);
console.log("forward collision corners", fCollC); ccps = fCollC.filter(cornerCollisionPosition({ x, y }, s.velocity));
ccps = collC.map(cornerCollisionPosition({ x, y }, s.velocity));
// console.log("corner collision position", ccps); // console.log("corner collision position", ccps);
current = s.collision; current = s.collision;
s.collision = detectCollisions(position, allWallCorners, collE); // s.collision = detectCollisions(position, allWallCorners, collE);
s.collision = cwcd.find(c => {
const d = distance(c.corner.x, c.corner.y, xc, yc);
const positionSeg = { xa: xc, ya: yc, xb: x, yb: y };
const slopeps = slope(positionSeg);
const posNormIntxn = perpIntxn(slopeps, 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;
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));
return d <= shipRadius || (s >= 0 && t <= 1);
});
// legs.style.display = !legs.style.display || legs.style.display === "none" ? "initial" : "none"; // legs.style.display = !legs.style.display || legs.style.display === "none" ? "initial" : "none";
legs.style.display = s.gearDown ? "initial" : "none"; legs.style.display = s.gearDown ? "initial" : "none";
if (!current && s.collision) { if (!current && s.collision) {
const baseSlope = slope(s.collision.edge); // const baseSlope = slope(s.collision.edge);
if (Object.is(baseSlope, 0) && s.gearDown) s.isLanded = true; // if (Object.is(baseSlope, 0) && s.gearDown) s.isLanded = true;
const clPos = collisionPosition(s.collision.edge, s.position, s.velocity, s.gearDown && Object.is(baseSlope, 0) ? shipRadius + 1 : shipRadius); // const clPos = collisionPosition(s.collision.edge, s.position, s.velocity, s.gearDown && Object.is(baseSlope, 0) ? shipRadius + 1 : shipRadius);
const diffx = xc - x;
const diffy = yc - y;
const detv = xc * y - yc * x;
const dv = Math.sqrt(diffy ** 2 + diffx ** 2);
const slopep = slope({ xa: x, ya: y, xb: xc, yb: yc });
const posNormIntxn = perpIntxn(slopep, x, y, s.collision.corner.x, s.collision.corner.y);
const d = Math.abs(diffy * s.collision.corner.x - diffx * s.collision.corner.y + detv) / dv;
const b = Math.sqrt(Math.max(shipRadius, d) ** 2 - Math.min(shipRadius, d) ** 2);
const cl = document.createElementNS(namespaceURIsvg, 'line');
cl.setAttribute('x1', posNormIntxn.x);
cl.setAttribute('y1', posNormIntxn.y);
cl.setAttribute('x2', x);
cl.setAttribute('y2', y);
const posP = cl.getPointAtLength(b);
s.velocity = { x: 0, y: 0 }; s.velocity = { x: 0, y: 0 };
s.position = { x: clPos.x, y: clPos.y } s.position = { x: posP.x, y: posP.y }
s.node.style.transform = `translate(${s.position.x}px, ${s.position.y}px)`; s.node.style.transform = `translate(${s.position.x}px, ${s.position.y}px)`;
} else if (current && s.collision) { } else if (current && s.collision) {
s.velocity = { x: 0, y: 0 }; s.velocity = { x: 0, y: 0 };

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 40 KiB