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)}°`, ]; } } } }