diff --git a/html/images/space.svg b/html/images/space.svg index ecb4e78..fca9026 100644 --- a/html/images/space.svg +++ b/html/images/space.svg @@ -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 };