Train movement rewrite
This commit is contained in:
parent
01081706b1
commit
9587ce5ae6
@ -6,50 +6,85 @@ import { getContextItem } from "../lib/context.ts";
|
||||
export class Tender extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(25, resources.get<HTMLImageElement>("snr:sprite/engine")!, 40, 20, {
|
||||
super(
|
||||
25,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
40,
|
||||
20,
|
||||
{
|
||||
at: new Vector(80, 0),
|
||||
width: 40,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class Tank extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
||||
super(
|
||||
50,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
70,
|
||||
20,
|
||||
{
|
||||
at: new Vector(80, 20),
|
||||
width: 70,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class YellowDumpCar extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
||||
super(
|
||||
50,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
70,
|
||||
20,
|
||||
{
|
||||
at: new Vector(80, 40),
|
||||
width: 70,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class GrayDumpCar extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
||||
super(
|
||||
50,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
70,
|
||||
20,
|
||||
{
|
||||
at: new Vector(80, 60),
|
||||
width: 70,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class NullCar extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
||||
super(
|
||||
50,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
70,
|
||||
20,
|
||||
{
|
||||
at: new Vector(80, 80),
|
||||
width: 70,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,50 +6,85 @@ import { ResourceManager } from "../lib/resources.ts";
|
||||
export class RedEngine extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
||||
super(
|
||||
55,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
80,
|
||||
20,
|
||||
{
|
||||
at: new Vector(0, 60),
|
||||
width: 80,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class PurpleEngine extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
||||
super(
|
||||
55,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
80,
|
||||
20,
|
||||
{
|
||||
at: new Vector(0, 60),
|
||||
width: 80,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class GreenEngine extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
||||
super(
|
||||
55,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
80,
|
||||
20,
|
||||
{
|
||||
at: new Vector(0, 40),
|
||||
width: 80,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class GrayEngine extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
||||
super(
|
||||
55,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
80,
|
||||
20,
|
||||
{
|
||||
at: new Vector(0, 20),
|
||||
width: 80,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
export class BlueEngine extends TrainCar {
|
||||
constructor() {
|
||||
const resources = getContextItem<ResourceManager>("resources");
|
||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
||||
super(
|
||||
55,
|
||||
10,
|
||||
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||
80,
|
||||
20,
|
||||
{
|
||||
at: new Vector(0, 0),
|
||||
width: 80,
|
||||
height: 20,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { Doodler, Vector } from "@bearmetal/doodler";
|
||||
import { Spline, TrackSegment, TrackSystem } from "../track/system.ts";
|
||||
import { Debuggable } from "../lib/debuggable.ts";
|
||||
import { map } from "../math/lerp.ts";
|
||||
import { off } from "node:process";
|
||||
|
||||
export class Train extends Debuggable {
|
||||
nodes: Vector[] = [];
|
||||
@ -14,10 +15,12 @@ export class Train extends Debuggable {
|
||||
|
||||
spacing = 20;
|
||||
|
||||
speed = 10;
|
||||
speed = 0;
|
||||
|
||||
get segments() {
|
||||
return Array.from(new Set(this.cars.flatMap((c) => c.segments)));
|
||||
return Array.from(
|
||||
new Set(this.cars.flatMap((c) => c.segments.values().toArray())),
|
||||
);
|
||||
}
|
||||
|
||||
constructor(track: Spline<TrackSegment>, cars: TrainCar[]) {
|
||||
@ -29,24 +32,22 @@ export class Train extends Debuggable {
|
||||
let currentOffset = 0;
|
||||
try {
|
||||
for (const car of this.cars) {
|
||||
currentOffset += this.spacing;
|
||||
const a = this.path.followEvenPoints(this.t - currentOffset);
|
||||
currentOffset += car.length;
|
||||
const b = this.path.followEvenPoints(this.t - currentOffset);
|
||||
car.points = [a.p, b.p];
|
||||
this.nodes.push(a.p, b.p);
|
||||
car.segments = [a.segmentId, b.segmentId];
|
||||
car.train = this;
|
||||
currentOffset += car.moveAlongPath(this.t - currentOffset) +
|
||||
this.spacing;
|
||||
}
|
||||
console.log("forward");
|
||||
} catch {
|
||||
currentOffset = 0;
|
||||
console.log("Reversed");
|
||||
for (const car of this.cars.toReversed()) {
|
||||
currentOffset += this.spacing;
|
||||
for (const [i, bogie] of car.bogies.entries().toArray().reverse()) {
|
||||
currentOffset += bogie.length;
|
||||
const a = this.path.followEvenPoints(this.t - currentOffset);
|
||||
currentOffset += car.length;
|
||||
const b = this.path.followEvenPoints(this.t - currentOffset);
|
||||
car.points = [a.p, b.p];
|
||||
this.nodes.push(a.p, b.p);
|
||||
car.segments = [a.segmentId, b.segmentId];
|
||||
car.setBogiePosition(a.p, i);
|
||||
this.nodes.push(a.p);
|
||||
car.segments.add(a.segmentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,16 +59,18 @@ export class Train extends Debuggable {
|
||||
let currentOffset = 0;
|
||||
for (const car of this.cars) {
|
||||
// This needs to be moved to the car itself
|
||||
if (!car.points) return;
|
||||
const [a, b] = car.points;
|
||||
const nA = this.path.followEvenPoints(this.t - currentOffset);
|
||||
a.set(nA.p);
|
||||
currentOffset += car.length;
|
||||
const nB = this.path.followEvenPoints(this.t - currentOffset);
|
||||
b.set(nB.p);
|
||||
currentOffset += this.spacing;
|
||||
car.segments = [nA.segmentId, nB.segmentId];
|
||||
// if (!car.points) return;
|
||||
// const [a, b] = car.points;
|
||||
// const nA = this.path.followEvenPoints(this.t - currentOffset);
|
||||
// a.set(nA.p);
|
||||
// currentOffset += car.length;
|
||||
// const nB = this.path.followEvenPoints(this.t - currentOffset);
|
||||
// b.set(nB.p);
|
||||
// currentOffset += this.spacing;
|
||||
// car.segments = [nA.segmentId, nB.segmentId];
|
||||
// car.draw();
|
||||
|
||||
currentOffset += car.moveAlongPath(this.t - currentOffset) + this.spacing;
|
||||
}
|
||||
// this.draw();
|
||||
}
|
||||
@ -118,7 +121,7 @@ export class Train extends Debuggable {
|
||||
colors.push(colors.shift()!);
|
||||
colors.push(colors.shift()!);
|
||||
colors.push(colors.shift()!);
|
||||
for (const [i, segmentId] of this.segments.entries()) {
|
||||
for (const [i, segmentId] of this.segments.entries().toArray()) {
|
||||
const segment = track.getSegment(segmentId);
|
||||
segment &&
|
||||
doodler.drawBezier(...segment.points, {
|
||||
@ -134,6 +137,12 @@ export class Train extends Debuggable {
|
||||
}
|
||||
}
|
||||
|
||||
interface Bogie {
|
||||
pos: Vector;
|
||||
angle: number;
|
||||
length: number;
|
||||
}
|
||||
|
||||
export class TrainCar extends Debuggable {
|
||||
img: HTMLImageElement;
|
||||
imgWidth: number;
|
||||
@ -143,10 +152,15 @@ export class TrainCar extends Debuggable {
|
||||
points?: [Vector, Vector, ...Vector[]];
|
||||
length: number;
|
||||
|
||||
segments: string[] = [];
|
||||
bogies: Bogie[] = [];
|
||||
|
||||
segments: Set<string> = new Set();
|
||||
|
||||
train?: Train;
|
||||
|
||||
constructor(
|
||||
length: number,
|
||||
trailing: number,
|
||||
img: HTMLImageElement,
|
||||
w: number,
|
||||
h: number,
|
||||
@ -158,14 +172,51 @@ export class TrainCar extends Debuggable {
|
||||
this.imgWidth = w;
|
||||
this.imgHeight = h;
|
||||
this.length = length;
|
||||
|
||||
this.bogies = [
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
angle: 0,
|
||||
length: length,
|
||||
},
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
angle: 0,
|
||||
length: trailing,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
setBogiePosition(pos: Vector, idx: number) {
|
||||
this.bogies[idx].pos.set(pos);
|
||||
}
|
||||
|
||||
update(dTime: number, t: number) {
|
||||
if (this.train) {
|
||||
for (const [i, bogie] of this.bogies.entries()) {
|
||||
const a = this.train.path.followEvenPoints(t - this.length * i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moveAlongPath(t: number): number {
|
||||
if (!this.train) return 0;
|
||||
let offset = 0;
|
||||
this.segments.clear();
|
||||
for (const [i, bogie] of this.bogies.entries()) {
|
||||
const a = this.train.path.followEvenPoints(t - offset);
|
||||
offset += bogie.length;
|
||||
this.setBogiePosition(a.p, i);
|
||||
this.segments.add(a.segmentId);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
draw() {
|
||||
if (!this.points) return;
|
||||
const doodler = getContextItem<Doodler>("doodler");
|
||||
const [a, b] = this.points;
|
||||
const origin = Vector.add(Vector.sub(a, b).div(2), b);
|
||||
const angle = Vector.sub(b, a).heading();
|
||||
const [a, b] = this.bogies;
|
||||
const origin = Vector.add(Vector.sub(a.pos, b.pos).div(2), b.pos);
|
||||
const angle = Vector.sub(b.pos, a.pos).heading();
|
||||
|
||||
doodler.drawCircle(origin, 4, { color: "blue" });
|
||||
|
||||
@ -187,11 +238,19 @@ export class TrainCar extends Debuggable {
|
||||
});
|
||||
}
|
||||
override debugDraw(...args: unknown[]): void {
|
||||
if (!this.points) return;
|
||||
const doodler = getContextItem<Doodler>("doodler");
|
||||
doodler.drawLine(this.points, {
|
||||
doodler.drawLine(this.bogies.map((b) => b.pos), {
|
||||
color: "blue",
|
||||
weight: 3,
|
||||
weight: 2,
|
||||
});
|
||||
doodler.deferDrawing(() => {
|
||||
const colors = getContextItem<string[]>("colors");
|
||||
for (const [i, b] of this.bogies.entries()) {
|
||||
doodler.drawCircle(b.pos, 5, { color: colors[i % colors.length] });
|
||||
doodler.fillText(b.length.toString(), b.pos.copy().add(10, 0), 100, {
|
||||
color: "white",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user