Merge branch 'dev'

This commit is contained in:
Ladd 2026-01-05 01:45:36 -06:00
commit 7733b5262a
9 changed files with 45 additions and 25 deletions

2
deploy
View File

@ -15,4 +15,4 @@ elif [[ $(hostname) == "lentilz" ]]; then
fi fi
echo >&2 echo >&2
echo >&2 "Deployed to https://laddhoffman.com/gravity/" echo >&2 "Deployed to https://gravity.laddhoffman.com"

View File

@ -31,6 +31,9 @@ export class MassObject {
forces = []; // [{x, y}] forces = []; // [{x, y}]
history = []; history = [];
alive = true; alive = true;
kineticEnergy = 0;
workDoneByPointer = 0;
workDoneByForces = 0;
currentPosition = undefined; currentPosition = undefined;
currentAcceleration = undefined; currentAcceleration = undefined;
@ -56,7 +59,8 @@ export class MassObject {
color: this.color, color: this.color,
timeCreated: this.timeCreated, timeCreated: this.timeCreated,
alive: this.alive, alive: this.alive,
// TODO: optional export history workDoneByPointer: this.workDoneByPointer,
workDoneByForces: this.workDoneByForces,
}; };
} }
@ -69,8 +73,9 @@ export class MassObject {
this.color = obj.color; this.color = obj.color;
this.timeCreated = obj.timeCreated; this.timeCreated = obj.timeCreated;
this.alive = obj.alive; this.alive = obj.alive;
// TODO: optional import history
this.history = []; this.history = [];
this.workDoneByPointer = obj.workDoneByPointer;
this.workDoneByForces = obj.workDoneByForces;
} }
get age() { get age() {

View File

@ -30,13 +30,12 @@ export class Panning {
toJSON() { toJSON() {
return { return {
velocity: this.velocity, velocity: this.velocity,
paused: this.paused,
}; };
} }
fromJSON({velocity, paused}) { fromJSON({velocity}) {
this.velocity = copy(velocity); this.velocity = copy(velocity);
this.paused = paused; this.paused = true;
} }
handlePointerDown({x, y}) { handlePointerDown({x, y}) {

View File

@ -46,10 +46,10 @@ export class Pointer {
}); });
window.addEventListener('focus', () => { window.addEventListener('focus', () => {
console.log('window focus'); // console.log('window focus');
}); });
window.addEventListener('blur', () => { window.addEventListener('blur', () => {
console.log('window blur'); // console.log('window blur');
}); });
} }

View File

@ -141,6 +141,7 @@ export class Sim {
} }
fromJSON(state) { fromJSON(state) {
this.pause();
this.system.fromJSON(state.system); this.system.fromJSON(state.system);
this.panning.fromJSON(state.panning); this.panning.fromJSON(state.panning);
this.display.fromJSON(state.display); this.display.fromJSON(state.display);

4
sync
View File

@ -16,9 +16,9 @@ do_rsync() {
} }
do_rsync ~/code/gravity-dev/ lentilz:code/gravity-dev/ do_rsync ~/code/gravity-dev/ lentilz:code/gravity-dev/
do_rsync lentilz:code/gravity-dev/ ~/code/gravity-dev/ # do_rsync lentilz:code/gravity-dev/ ~/code/gravity-dev/
git status git status
echo >&2 echo >&2
echo >&2 "Synced with https://laddhoffman.com/gravity-dev/" echo >&2 "Synced with https://gravity.dev.laddhoffman.com"

View File

@ -68,7 +68,11 @@ export class System {
const obj = this.getSelectedOrCreating(); const obj = this.getSelectedOrCreating();
if (obj === undefined) return; if (obj === undefined) return;
const start = this.selectedObjectStart; const start = this.selectedObjectStart;
obj.position = add(start, sub(r, start.pointer)); const delta = sub(r, start.pointer);
// TODO: Calculate work done by pointer here?
// Either interpolate the acceleration and use m*a, or
// measure the change in the object's kinetic energy
obj.position = add(start, delta);
obj.velocity = zero; obj.velocity = zero;
} }
@ -171,8 +175,8 @@ export class System {
const delta = sub(obj.currentPosition, obj.position); const delta = sub(obj.currentPosition, obj.position);
const netForce = mult(obj.acceleration, obj.mass); const netForce = mult(obj.acceleration, obj.mass);
const work = dot(netForce, delta); const work = dot(netForce, delta);
console.log('work', work);
obj.position = obj.currentPosition; obj.position = obj.currentPosition;
obj.workDoneByPointer += work;
} }
// Append to object history // Append to object history
@ -408,11 +412,20 @@ export class System {
// Equal and opposite forces // Equal and opposite forces
A.forces.push({x: Fx, y: Fy}); A.forces.push({x: Fx, y: Fy});
B.forces.push({x: -Fx, y: -Fy}); B.forces.push({x: -Fx, y: -Fy});
if (A.currentPosition && B.currentPosition) {
A.workDoneByForces += dot({x: Fx, y: Fy}, sub(A.position, A.currentPosition));
B.workDoneByForces += dot({x: Fx, y: Fy}, sub(B.position, B.currentPosition));
}
}, {alive: true, startWith: i + 1}); }, {alive: true, startWith: i + 1});
}); });
// Also compute acceleration
// Additional computations
this.forEachObject(obj => { this.forEachObject(obj => {
// Acceleration
obj.acceleration = obj.getAcceleration(); obj.acceleration = obj.getAcceleration();
// Kinetic Energy
obj.kineticEnergy = obj.mass * square(obj.velocity) / 2;
}); });
} }

View File

@ -1,6 +1,5 @@
import {hide, show} from '../helper.js'; import {hide, show} from '../helper.js';
import {Tool} from '../tool.js'; import {Tool} from '../tool.js';
import {add, magnitude, sub} from '../vector.js';
export class ObjectsTool extends Tool { export class ObjectsTool extends Tool {
objects = []; objects = [];
@ -58,17 +57,22 @@ export class ObjectsTool extends Tool {
obj.objectsToolEl = objectEl; obj.objectsToolEl = objectEl;
const {r, g, b} = obj.color; const {r, g, b} = obj.color;
// Distance from center of screen // Distance from center of screen
const distance = magnitude(sub(obj.position, add(this.sim.display.viewOrigin, { // const distance = magnitude(sub(obj.position, add(this.sim.display.viewOrigin, {
x: this.sim.display.width / 2, // x: this.sim.display.width / 2,
y: this.sim.display.height / 2, // y: this.sim.display.height / 2,
}))); // })));
objectEl.innerHTML = ` objectEl.innerHTML =
<span style="background-color: rgb(${r},${g},${b});">` + `<span style="background-color: rgb(${r},${g},${b});">&nbsp;&nbsp;</span>` +
'&nbsp;&nbsp;</span>' + `E<sub>k</sub>: ${obj.kineticEnergy.toFixed(0)}` +
`${obj.mass.toPrecision(3)} ` + `<br>&nbsp;&nbsp;W<sub>p</sub>: ${obj.workDoneByPointer.toFixed(0)}` +
`${distance.toPrecision(3)}`; `<br>&nbsp;&nbsp;W<sub>f</sub>: ${obj.workDoneByForces.toFixed(0)}`;
// `${obj.mass.toPrecision(3)} ` +
// `${distance.toPrecision(3)}`;
// `${magnitude(obj.velocity).toExponential(0)} ` + // `${magnitude(obj.velocity).toExponential(0)} ` +
// `${-degrees(direction(obj.velocity)).toFixed(0)}°`; // `${-degrees(direction(obj.velocity)).toFixed(0)}°`;
if (!obj.hidden) { if (!obj.hidden) {
show({ show({
items: this.objects, items: this.objects,

View File

@ -56,7 +56,6 @@ export class StateTool extends Tool {
throw new Error('state query parameter does not match digest query parameter'); throw new Error('state query parameter does not match digest query parameter');
} }
// Tools in this system can be very powerful // Tools in this system can be very powerful
this.sim.pause();
this.sim.fromJSON(state); this.sim.fromJSON(state);
} }
} }
@ -99,7 +98,6 @@ export class StateTool extends Tool {
load.addEventListener('click', (e) => { load.addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
// Tools in this system can wield great power // Tools in this system can wield great power
this.sim.pause();
this.sim.fromJSON(state); this.sim.fromJSON(state);
}); });