This commit is contained in:
2026-01-07 12:58:06 -08:00
parent e9a86c532e
commit 5c5c76f9a1

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg viewBox="-200 -150 400 300" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- <svg viewBox="-10 -10 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg"> -->
<!-- <svg viewBox="-200 -150 400 300" version="1.1" xmlns="http://www.w3.org/2000/svg"> -->
<svg viewBox="-10 -10 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>
foreignObject {
font-size: 4pt;
@@ -186,6 +186,24 @@
</foreignObject>
<script type="text/javascript">//<![CDATA[
// entities
// const Ships = [{ entity_id: "ship_1" }];
// const Walls = [{ entity_id: "wall_1" }, { entity_id: "wall_2" }];
// systems
// Move.update = ({ entity_id }) => {
// reads Velocity[entity_id]
// sets Position[entity_id]
// };
// components
// Velocity = { "ship_1": { x: 0, y: 0 }};
// Position = { "ship_1": { x: 0, y: 0 }};
// Points = {
// "wall_1": "0,0 2,0 1,1",
// "wall_2": "0,0 -1,1 -2,0",
// };
const namespaceURIsvg = 'http://www.w3.org/2000/svg';
const degsRegex = /(-?\d*\.{0,1}\d+)deg/g;
const regex = /(-?\d*\.{0,1}\d+)px/g;
@@ -208,11 +226,11 @@
const s = {
position: { x: 0, y: 0 },
velocity: { x: 0, y: 0 },
// velocity: { x: 0, y: 0 },
// velocity: { x: -100, y: -100 },
// velocity: { x: 5, y: 7 },
// velocity: { x: 5*mult, y: 8*mult },
// velocity: { x: 2, y: 7 },
velocity: { x: 2*mult, y: 7*mult },
// acceleration: { x: 5, y: 7 },
acceleration: { x: 0, y: 0 },
rotate: 0,
@@ -271,25 +289,11 @@
});
const edges = corners.map(({ x: xa, y: ya }, i, arr) => {
// return [+x, +y];
// const [xb, yb] = arr[i]++;
const { x: xb, y: yb } = arr[(i + 1) % arr.length];
// console.log("coords", { xa: +x, ya: +y, xb: +xb, yb: +yb, inverse: wall.classList.contains("inverse") });
// return `${+x},${+y} ${+xb},${+yb}`;
return {
xa: xa,
ya: ya,
xb: xb,
yb: yb,
};
return { xa: xa, ya: ya, xb: xb, yb: yb };
});
return {
node,
corners,
edges
};
return { node, corners, edges };
});
const mcs = ws.reduce(
@@ -389,40 +393,15 @@
}, []);
}
function getCollisionEdges(walls, [xc, yc]) {
return walls.reduce((acc, wall) => {
return [...acc, ...wall.edges.filter(({ xa, ya, xb, yb }) => {
return [isClockwise, isAcute].every(c => c([xa, ya], [xb, yb], [xc, yc]));
}).map(edge => ({ edge, wall }))];
}, []);
function getForwardEdges(edges, { x, y }) {
return edges.filter(({ edge }) => {
const { xa, ya, xb, yb } = edge;
const det = (xb - xa) * (y - ya) - (x - xa) * (yb - ya);
return det < 0;
});
}
// function getCollisionCorners(ws, { x: px, y: py }, { x: vx, y: vy }) {
function getCollisionCorners(ws, { 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 ws.reduce((acc, w) => {
const filtered = w.corners.filter(c => {
const { x: x0, y: y0 } = c;
const velNormIntxn = perpIntxn(slopev, x1, y1, x0, y0);
// const d = distance(velNormIntxn.x, velNormIntxn.y , x0, y0);
// https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points
const d = Math.abs(diffy * x0 - diffx * y0 + detv) / dv;
// console.log("corner", c, "d", d, "shipRadius", shipRadius);
return d <= shipRadius;
}).map(c => ({ corner: c, node: w.node }));
// });
return [...acc, ...filtered];
}, []);
}
function getForwardCollisionCorners(walls, position, velocity) {
function getForwardCorners(walls, position, velocity) {
const { x: x1, y: y1 } = position;
const { x: x2, y: y2 } = velocity;
@@ -611,6 +590,16 @@
return el;
}
function drawCircle(cx, cy, color = "black", r = 1) {
const el = document.createElementNS(namespaceURIsvg, 'circle');
el.setAttribute('cx', cx);
el.setAttribute('cy', cy);
el.setAttribute('r', r);
el.setAttribute('fill', color);
svg.appendChild(el);
return el;
}
function slope({ xa, ya, xb, yb }) {
return (yb - ya) / (xb - xa);
}
@@ -645,6 +634,16 @@
const roundedT = +t.toFixed(2);
const roundedS = +s.toFixed(2);
if (roundedS >= 0 && roundedS <= 1 && roundedT >= 0 && roundedT <= 1) {
const xs = (x1 + s * (x2 - x1));
const ys = (y1 + s * (y2 - y1));
const xt = (x3 + t * (x4 - x3));
const yt = (y3 + t * (y4 - y3));
const collisionPt = [xs, ys];
// [xs, ys] === [xt, yt];
drawCircle(...collisionPt, "red"); // collision position
}
return roundedS >= 0 && roundedS <= 1 && roundedT >= 0 && roundedT <= 1;
};
}
@@ -666,12 +665,28 @@
const { xa: x1, ya: y1, xb: x2, yb: y2 } = positionSeg;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = cornerSeg;
drawLine(x1, y1, x2, y2);
drawLine(x3, y3, x4, y4);
// 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(...sCollisionPt, "red");
drawCircle(...tCollisionPt, "blue");
}
return s >= 0 && roundedT <= 1;
};
}
@@ -776,22 +791,16 @@
let [xc, yc] = position;
// console.log("future position", xc, yc);
const efs = mes.filter(({ edge, wall }) => {
const { xa, ya, xb, yb } = edge;
const det = (xb - xa) * (y - ya) - (x - xa) * (yb - ya);
return det < 0;
});
const efs = getForwardEdges(mes, { x, y })
// console.log("edges facing ship", efs);
const edgeColl = efs.find(detectEdgeCollision([xc, yc], [x, y], shipRadius));
// corners ahead of ship
const fCollC = getForwardCollisionCorners(ws, { x, y }, s.velocity);
// console.log("corners ahead of ship", fCollC);
const fCollC = getForwardCorners(ws, { x, y }, s.velocity);
// corners within collision distance
// corners within collision distance (are on the collision path)
cwcd = fCollC.filter(withinCollisionDistance({ x, y }, s.velocity));
// console.log("corners on collision path", cwcd);
const cornerColl = cwcd.find(detectCornerCollision([xc, yc], [x, y], shipRadius));
current = s.collision;
@@ -806,7 +815,7 @@
// const baseSlope = slope(s.collision.edge);
// if (Object.is(baseSlope, 0) && s.gearDown) s.isLanded = true;
s.isLanded = true;
let posP;
if (s.collision.corner) {
posP = cornerContactPosition(xc, yc, x, y, s.collision.corner, shipRadius);

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB