gravity/objects.js

116 lines
2.9 KiB
JavaScript

import { MassObject } from './object.js';
import {
MASS_CREATION_RATE,
DISPLAY_OBJECTS_INFO,
MOTION_TIME_SCALE,
} from './config.js';
export class Objects {
objects = [];
creatingObject = undefined;
selectedObject = undefined;
constructor(sim) {
this.sim = sim;
}
// Create an object with mass that grows as pointer is held down
createObject(x, y) {
const idx = this.objects.length;
const obj = new MassObject(x, y, idx);
this.creatingObject = idx;
this.objects.push(obj);
}
doneCreatingObject() {
this.creatingObject = undefined;
}
object(i) {
return this.objects[i];
}
selectObject(i) {
this.selectedObject = i;
}
deselect() {
this.selectedObject = undefined;
}
getSelectedOrCreating() {
let i = this.creatingObject ?? this.selectedObject;
if (i !== undefined) {
return this.objects[i];
}
}
get length() {
return this.objects.length;
}
objectAtLocation(x, y) {
for (let i = 0; i < this.objects.length; i++) {
const obj = this.objects[i];
// If distance to object is less than object's radius, we are touching the object
const dist = Math.pow((obj.position.x - x)**2 + (obj.position.y - y)**2, 1/2);
if (dist <= obj.radius) {
return i;
}
}
}
handlePointerDown({x, y}) {
// If pointer is touching an object, select the object
const touchingObject = this.objectAtLocation(x, y);
if (touchingObject !== undefined) {
this.selectObject(touchingObject);
} else {
// Otherwise, create a new object
this.createObject(x, y);
}
}
handlePointerUp({x, y}) {
this.doneCreatingObject();
this.deselect();
}
computeFrame(elapsedTime) {
// If we're creating an object, increment its mass
// with the mass creation rate accelerating over time
if (this.creatingObject !== undefined) {
const obj = this.objects[this.creatingObject];
const rate = MASS_CREATION_RATE * obj.age;
obj.mass += rate * elapsedTime;
}
if (this.sim.playing) {
// Update positions. Simple Euler method for now.
for (let i = 0; i < this.objects.length; i++) {
const obj = this.objects[i];
obj.position.x += obj.velocity.x * MOTION_TIME_SCALE;
obj.position.y += obj.velocity.y * MOTION_TIME_SCALE;
}
}
// Display objects info
if (DISPLAY_OBJECTS_INFO) {
for (let i = 0; i < this.objects.length; i++) {
const obj = this.objects[i];
const speed = Math.pow(obj.velocity.x ** 2 + obj.velocity.y ** 2, 1/2);
// Invert y so that the angle is counterclockwise from x-axis
const direction = Math.atan2(-obj.velocity.y, obj.velocity.x) * 180 / Math.PI;
this.sim.info[`Object ${i}`] = [
`${obj.position.x}, `,
`${obj.position.y}, `,
`${obj.mass.toPrecision(6)} kg, `,
`${speed.toPrecision(2)} m/s, ${direction.toPrecision(2)}°`,
];
}
}
}
}