Corner collisions
This commit is contained in:
@@ -189,16 +189,18 @@
|
||||
let acceleration; // meters per second per second
|
||||
let rotate = 0;
|
||||
|
||||
let mult = 20;
|
||||
let mult = 1000;
|
||||
|
||||
const s = {
|
||||
position: { x: 0, y: 0 },
|
||||
velocity: { x: 5, y: -10 },
|
||||
// velocity: { x: 5*mult, y: -10*mult },
|
||||
// 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: 0 },
|
||||
// velocity: { x: -10, y: 0 },
|
||||
// velocity: { x: 10, y: 0 },
|
||||
// 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 es = wall.getAttribute('points').split(' ').map((coords, i, arr) => {
|
||||
const [x, y] = coords.split(',');
|
||||
@@ -406,15 +415,10 @@
|
||||
function getForwardCollisionCorners(walls, position, velocity) {
|
||||
const { x: x1, y: y1 } = position;
|
||||
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;
|
||||
|
||||
// console.log("velocity", velocity, "position", position);
|
||||
let perppts;
|
||||
let perppts = {};
|
||||
|
||||
if (vx === 0 && vy === 0) {
|
||||
// none
|
||||
@@ -460,15 +464,15 @@
|
||||
}
|
||||
|
||||
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) => {
|
||||
const filtered = w.corners.filter(c => {
|
||||
const filtered = a && b ? w.corners.filter(c => {
|
||||
// https://stackoverflow.com/a/1560510
|
||||
|
||||
const det = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
|
||||
return det > 0;
|
||||
});
|
||||
}).map(c => ({ corner: c, node: w.node })) : [];
|
||||
|
||||
return [...acc, ...filtered];
|
||||
}, []);
|
||||
@@ -661,6 +665,62 @@
|
||||
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 }) {
|
||||
// todo1: i only want the collisions ahead, not behind
|
||||
// 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 }) => {
|
||||
const velNormIntxn = perpIntxn(slopev, x1, y1, x0, y0);
|
||||
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');
|
||||
cl.setAttribute('x1', velNormIntxn.x);
|
||||
@@ -756,36 +818,83 @@
|
||||
const changeY = 0.001 * elapsed * velocityY;
|
||||
|
||||
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);
|
||||
// let position = [positionX, positionY] = restart ? [0, 0] : wrapPos(changeX + x, changeY + y);
|
||||
let position = [positionX, positionY] = [changeX + x, changeY + y];
|
||||
let [xc, yc] = position;
|
||||
// console.log("future position", xc, yc);
|
||||
console.log("future position", xc, yc);
|
||||
|
||||
const collE = getCollisionEdges(edgeszz, position);
|
||||
// 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);
|
||||
|
||||
// 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("forward collision corners", fCollC);
|
||||
ccps = collC.map(cornerCollisionPosition({ x, y }, s.velocity));
|
||||
ccps = fCollC.filter(cornerCollisionPosition({ x, y }, s.velocity));
|
||||
// console.log("corner collision position", ccps);
|
||||
|
||||
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 = s.gearDown ? "initial" : "none";
|
||||
|
||||
if (!current && s.collision) {
|
||||
const baseSlope = slope(s.collision.edge);
|
||||
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 baseSlope = slope(s.collision.edge);
|
||||
// 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 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.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)`;
|
||||
} else if (current && s.collision) {
|
||||
s.velocity = { x: 0, y: 0 };
|
||||
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 40 KiB |
Reference in New Issue
Block a user