trainsim/physics/mover.ts

112 lines
2.9 KiB
TypeScript

import { Vector } from "../math/vector.ts";
export class Mover {
position: Vector;
velocity: Vector;
acceleration: Vector;
maxSpeed: number;
maxForce: number;
_trailingPoint: number;
protected _leadingPoint: number;
get trailingPoint() {
const desired = this.velocity.copy();
desired.normalize();
desired.mult(-this._trailingPoint);
return Vector.add(this.position, desired);
}
get leadingPoint() {
const desired = this.velocity.copy();
desired.normalize();
desired.mult(this._leadingPoint);
return Vector.add(this.position, desired);
}
ctx?: CanvasRenderingContext2D;
boundingBox: {
pos: Vector;
size: Vector;
}
constructor();
constructor(random: boolean);
constructor(pos?: Vector, vel?: Vector, acc?: Vector);
constructor(posOrRandom?: Vector | boolean, vel?: Vector, acc?: Vector) {
if (typeof posOrRandom === 'boolean' && posOrRandom) {
this.position = Vector.random2D(new Vector());
this.velocity = Vector.random2D(new Vector());
this.acceleration = new Vector()
} else {
this.position = posOrRandom || new Vector();
this.velocity = vel || new Vector();
this.acceleration = acc || new Vector()
}
this.boundingBox = {
size: new Vector(20, 10),
pos: new Vector(this.position.x - 10, this.position.y - 5)
}
this.maxSpeed = 3;
this.maxForce = .3;
this._trailingPoint = 0;
this._leadingPoint = 0;
this.init();
}
init() {
//
}
move() {
this.velocity.limit(this.maxSpeed);
this.acceleration.limit(this.maxForce);
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.edges();
this.draw();
}
edges() {
if (!this.ctx) return;
if (this.position.x > this.ctx.canvas.width) this.position.x = 0;
if (this.position.y > this.ctx.canvas.height) this.position.y = 0;
if (this.position.x < 0) this.position.x = this.ctx.canvas.width;
if (this.position.y < 0) this.position.y = this.ctx.canvas.height;
}
draw() {
if (!this.ctx) return;
this.ctx.fillStyle = 'white'
this.ctx.save();
this.ctx.translate(this.position.x, this.position.y);
this.ctx.rotate(this.velocity.heading() || 0);
this.ctx.translate(-this.position.x, -this.position.y);
// this.ctx.rotate(Math.PI)
// this.ctx.rotate(.5);
this.ctx.translate(-(this.boundingBox.size.x / 2), -(this.boundingBox.size.y / 2));
this.ctx.fillRect(this.position.x, this.position.y, this.boundingBox.size.x, this.boundingBox.size.y);
this.ctx.restore();
}
setContext(ctx: CanvasRenderingContext2D) {
this.ctx = ctx;
}
applyForce(force: Vector) {
this.acceleration.add(force);
}
static edges(point: Vector, width: number, height: number) {
if (point.x > width) point.x = 0;
if (point.y > height) point.y = 0;
if (point.x < 0) point.x = width;
if (point.y < 0) point.y = height;
}
}