Graduate Orbit sim to its own thing
This commit is contained in:
parent
04cbe84c24
commit
063dd636bb
5 changed files with 105 additions and 87 deletions
|
@ -5,7 +5,7 @@
|
||||||
<body>
|
<body>
|
||||||
<script src="js/debug.js"></script>
|
<script src="js/debug.js"></script>
|
||||||
<script>
|
<script>
|
||||||
document.body.append(...OrbitDemo(), ...TickDebug());
|
document.body.append(...TickDebug());
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
4
debug.ts
4
debug.ts
|
@ -1,3 +1,3 @@
|
||||||
import { TickDebug, OrbitDemo } from "./debug/tick";
|
import { TickDebug } from "./debug/tick";
|
||||||
|
|
||||||
Object.assign(globalThis, { TickDebug, OrbitDemo });
|
Object.assign(globalThis, { TickDebug });
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { canvas2d, h } from "../lib/html";
|
import { h } from "../lib/html";
|
||||||
import { Cancel } from "../lib/source";
|
import { Cancel } from "../lib/source";
|
||||||
import { tick } from "../lib/tick";
|
import { tick } from "../lib/tick";
|
||||||
|
|
||||||
|
@ -34,86 +34,3 @@ export function TickDebug() {
|
||||||
|
|
||||||
return [h("h1", {}, "Tick Event Demo"), start, stop, output, h("hr")];
|
return [h("h1", {}, "Tick Event Demo"), start, stop, output, h("hr")];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OrbitDemo() {
|
|
||||||
const [canvas, cx] = canvas2d({
|
|
||||||
width: 512,
|
|
||||||
height: 512,
|
|
||||||
});
|
|
||||||
cx.scale(1 / 2, 1 / 2);
|
|
||||||
cx.translate(512, 512);
|
|
||||||
|
|
||||||
const G = 8000;
|
|
||||||
const PHYSICS_TICKS = 30;
|
|
||||||
const masses: {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
vx: number;
|
|
||||||
vy: number;
|
|
||||||
r: number;
|
|
||||||
m: number;
|
|
||||||
c: string;
|
|
||||||
}[] = [];
|
|
||||||
|
|
||||||
const tickSource = tick(PHYSICS_TICKS);
|
|
||||||
let cancel: Cancel;
|
|
||||||
|
|
||||||
const begin = () => {
|
|
||||||
// reset / init
|
|
||||||
cancel?.();
|
|
||||||
masses.length = 0;
|
|
||||||
masses.push(
|
|
||||||
{ x: 0, y: 0, vx: -1, vy: -2, r: 10, m: 1000, c: "yellow" },
|
|
||||||
{ x: -150, y: 150, vx: 130, vy: 130, r: 9, m: 10, c: "red" },
|
|
||||||
{ x: -450, y: 0, vx: 0, vy: 120, r: 4, m: 5, c: "#0f8" }
|
|
||||||
);
|
|
||||||
// subscribe to source, stash cancellation func
|
|
||||||
cancel = tickSource((tick) => {
|
|
||||||
switch (tick[0]) {
|
|
||||||
case "physics":
|
|
||||||
// apply velocities
|
|
||||||
masses.forEach((mass) => {
|
|
||||||
mass.x += mass.vx * (1 / PHYSICS_TICKS);
|
|
||||||
mass.y += mass.vy * (1 / PHYSICS_TICKS);
|
|
||||||
});
|
|
||||||
// apply accelerations
|
|
||||||
masses.forEach((mass) => {
|
|
||||||
masses.forEach((other) => {
|
|
||||||
if (mass != other) {
|
|
||||||
const dx = other.x - mass.x;
|
|
||||||
const dy = other.y - mass.y;
|
|
||||||
|
|
||||||
const rSquared = dx ** 2 + dy ** 2;
|
|
||||||
const f = (G * other.m) / rSquared;
|
|
||||||
const d = Math.sqrt(rSquared);
|
|
||||||
const fx = (f * dx) / d;
|
|
||||||
const fy = (f * dy) / d;
|
|
||||||
|
|
||||||
mass.vx += fx / PHYSICS_TICKS;
|
|
||||||
mass.vy += fy / PHYSICS_TICKS;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "render":
|
|
||||||
const [, dt] = tick;
|
|
||||||
cx.fillStyle = "black";
|
|
||||||
cx.fillRect(-512, -512, 1024, 1024);
|
|
||||||
masses.forEach(({ x, y, vx, vy, r, c }) => {
|
|
||||||
cx.fillStyle = c;
|
|
||||||
cx.beginPath();
|
|
||||||
cx.arc(x + vx * dt, y + vy * dt, r, 0, Math.PI * 2);
|
|
||||||
cx.fill();
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const end = () => cancel?.();
|
|
||||||
|
|
||||||
const start = h("button", { onclick: begin }, "Begin");
|
|
||||||
const stop = h("button", { onclick: end }, "Cease");
|
|
||||||
|
|
||||||
return [h("h1", {}, "Orbit Demo"), h("p", {}, start, stop), canvas, h("hr")];
|
|
||||||
}
|
|
||||||
|
|
11
orbit.html
Normal file
11
orbit.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Orbit Simulation</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="js/orbit.js"></script>
|
||||||
|
<script>
|
||||||
|
document.body.append(...OrbitDemo());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
90
orbit.ts
Normal file
90
orbit.ts
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
import { canvas2d, h } from "./lib/html";
|
||||||
|
import { Cancel } from "./lib/source";
|
||||||
|
import { tick } from "./lib/tick";
|
||||||
|
|
||||||
|
type Mass = {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
vx: number;
|
||||||
|
vy: number;
|
||||||
|
radius: number;
|
||||||
|
mass: number;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function OrbitDemo() {
|
||||||
|
const [canvas, cx] = canvas2d({
|
||||||
|
width: 512,
|
||||||
|
height: 512,
|
||||||
|
});
|
||||||
|
cx.scale(1 / 2, 1 / 2);
|
||||||
|
cx.translate(512, 512);
|
||||||
|
|
||||||
|
const G = 8000;
|
||||||
|
const PHYSICS_TICKS = 30;
|
||||||
|
const masses: Mass[] = [];
|
||||||
|
|
||||||
|
const tickSource = tick(PHYSICS_TICKS);
|
||||||
|
let cancel: Cancel;
|
||||||
|
|
||||||
|
const begin = () => {
|
||||||
|
// reset / init
|
||||||
|
cancel?.();
|
||||||
|
masses.length = 0;
|
||||||
|
masses.push(
|
||||||
|
{ x: 0, y: 0, vx: -1, vy: -2, radius: 10, mass: 1000, color: "yellow" },
|
||||||
|
{ x: -150, y: 150, vx: 130, vy: 130, radius: 9, mass: 10, color: "red" },
|
||||||
|
{ x: -450, y: 0, vx: 0, vy: 120, radius: 4, mass: 5, color: "#0f8" }
|
||||||
|
);
|
||||||
|
// subscribe to source, stash cancellation func
|
||||||
|
cancel = tickSource((tick) => {
|
||||||
|
switch (tick[0]) {
|
||||||
|
case "physics":
|
||||||
|
// apply velocities
|
||||||
|
masses.forEach((mass) => {
|
||||||
|
mass.x += mass.vx * (1 / PHYSICS_TICKS);
|
||||||
|
mass.y += mass.vy * (1 / PHYSICS_TICKS);
|
||||||
|
});
|
||||||
|
// apply accelerations
|
||||||
|
masses.forEach((mass) => {
|
||||||
|
masses.forEach((other) => {
|
||||||
|
if (mass != other) {
|
||||||
|
const dx = other.x - mass.x;
|
||||||
|
const dy = other.y - mass.y;
|
||||||
|
|
||||||
|
const rSquared = dx ** 2 + dy ** 2;
|
||||||
|
const f = (G * other.mass) / rSquared;
|
||||||
|
const d = Math.sqrt(rSquared);
|
||||||
|
const fx = (f * dx) / d;
|
||||||
|
const fy = (f * dy) / d;
|
||||||
|
|
||||||
|
mass.vx += fx / PHYSICS_TICKS;
|
||||||
|
mass.vy += fy / PHYSICS_TICKS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "render":
|
||||||
|
const [, dt] = tick;
|
||||||
|
cx.fillStyle = "black";
|
||||||
|
cx.fillRect(-512, -512, 1024, 1024);
|
||||||
|
masses.forEach(({ x, y, vx, vy, radius, color }) => {
|
||||||
|
cx.fillStyle = color;
|
||||||
|
cx.beginPath();
|
||||||
|
cx.arc(x + vx * dt, y + vy * dt, radius, 0, Math.PI * 2);
|
||||||
|
cx.fill();
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const end = () => cancel?.();
|
||||||
|
|
||||||
|
const start = h("button", { onclick: begin }, "Begin / Reset");
|
||||||
|
const stop = h("button", { onclick: end }, "Cease");
|
||||||
|
|
||||||
|
return [h("h1", {}, "Orbit Simulation"), h("p", {}, start, stop), canvas];
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(globalThis, { OrbitDemo });
|
Loading…
Add table
Reference in a new issue