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 {
|
export class Tender extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(25, resources.get<HTMLImageElement>("snr:sprite/engine")!, 40, 20, {
|
super(
|
||||||
at: new Vector(80, 0),
|
25,
|
||||||
width: 40,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
40,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(80, 0),
|
||||||
|
width: 40,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class Tank extends TrainCar {
|
export class Tank extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
super(
|
||||||
at: new Vector(80, 20),
|
50,
|
||||||
width: 70,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
70,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(80, 20),
|
||||||
|
width: 70,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class YellowDumpCar extends TrainCar {
|
export class YellowDumpCar extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
super(
|
||||||
at: new Vector(80, 40),
|
50,
|
||||||
width: 70,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
70,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(80, 40),
|
||||||
|
width: 70,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class GrayDumpCar extends TrainCar {
|
export class GrayDumpCar extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
super(
|
||||||
at: new Vector(80, 60),
|
50,
|
||||||
width: 70,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
70,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(80, 60),
|
||||||
|
width: 70,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class NullCar extends TrainCar {
|
export class NullCar extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(50, resources.get<HTMLImageElement>("snr:sprite/engine")!, 70, 20, {
|
super(
|
||||||
at: new Vector(80, 80),
|
50,
|
||||||
width: 70,
|
10,
|
||||||
height: 20,
|
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 {
|
export class RedEngine extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
super(
|
||||||
at: new Vector(0, 60),
|
55,
|
||||||
width: 80,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
80,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(0, 60),
|
||||||
|
width: 80,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class PurpleEngine extends TrainCar {
|
export class PurpleEngine extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
super(
|
||||||
at: new Vector(0, 60),
|
55,
|
||||||
width: 80,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
80,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(0, 60),
|
||||||
|
width: 80,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class GreenEngine extends TrainCar {
|
export class GreenEngine extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
super(
|
||||||
at: new Vector(0, 40),
|
55,
|
||||||
width: 80,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
80,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(0, 40),
|
||||||
|
width: 80,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class GrayEngine extends TrainCar {
|
export class GrayEngine extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
super(
|
||||||
at: new Vector(0, 20),
|
55,
|
||||||
width: 80,
|
10,
|
||||||
height: 20,
|
resources.get<HTMLImageElement>("snr:sprite/engine")!,
|
||||||
});
|
80,
|
||||||
|
20,
|
||||||
|
{
|
||||||
|
at: new Vector(0, 20),
|
||||||
|
width: 80,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class BlueEngine extends TrainCar {
|
export class BlueEngine extends TrainCar {
|
||||||
constructor() {
|
constructor() {
|
||||||
const resources = getContextItem<ResourceManager>("resources");
|
const resources = getContextItem<ResourceManager>("resources");
|
||||||
super(55, resources.get<HTMLImageElement>("snr:sprite/engine")!, 80, 20, {
|
super(
|
||||||
at: new Vector(0, 0),
|
55,
|
||||||
width: 80,
|
10,
|
||||||
height: 20,
|
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 { Spline, TrackSegment, TrackSystem } from "../track/system.ts";
|
||||||
import { Debuggable } from "../lib/debuggable.ts";
|
import { Debuggable } from "../lib/debuggable.ts";
|
||||||
import { map } from "../math/lerp.ts";
|
import { map } from "../math/lerp.ts";
|
||||||
|
import { off } from "node:process";
|
||||||
|
|
||||||
export class Train extends Debuggable {
|
export class Train extends Debuggable {
|
||||||
nodes: Vector[] = [];
|
nodes: Vector[] = [];
|
||||||
@ -14,10 +15,12 @@ export class Train extends Debuggable {
|
|||||||
|
|
||||||
spacing = 20;
|
spacing = 20;
|
||||||
|
|
||||||
speed = 10;
|
speed = 0;
|
||||||
|
|
||||||
get segments() {
|
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[]) {
|
constructor(track: Spline<TrackSegment>, cars: TrainCar[]) {
|
||||||
@ -29,24 +32,22 @@ export class Train extends Debuggable {
|
|||||||
let currentOffset = 0;
|
let currentOffset = 0;
|
||||||
try {
|
try {
|
||||||
for (const car of this.cars) {
|
for (const car of this.cars) {
|
||||||
currentOffset += this.spacing;
|
car.train = this;
|
||||||
const a = this.path.followEvenPoints(this.t - currentOffset);
|
currentOffset += car.moveAlongPath(this.t - currentOffset) +
|
||||||
currentOffset += car.length;
|
this.spacing;
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
console.log("forward");
|
||||||
} catch {
|
} catch {
|
||||||
currentOffset = 0;
|
currentOffset = 0;
|
||||||
|
console.log("Reversed");
|
||||||
for (const car of this.cars.toReversed()) {
|
for (const car of this.cars.toReversed()) {
|
||||||
currentOffset += this.spacing;
|
for (const [i, bogie] of car.bogies.entries().toArray().reverse()) {
|
||||||
const a = this.path.followEvenPoints(this.t - currentOffset);
|
currentOffset += bogie.length;
|
||||||
currentOffset += car.length;
|
const a = this.path.followEvenPoints(this.t - currentOffset);
|
||||||
const b = this.path.followEvenPoints(this.t - currentOffset);
|
car.setBogiePosition(a.p, i);
|
||||||
car.points = [a.p, b.p];
|
this.nodes.push(a.p);
|
||||||
this.nodes.push(a.p, b.p);
|
car.segments.add(a.segmentId);
|
||||||
car.segments = [a.segmentId, b.segmentId];
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,16 +59,18 @@ export class Train extends Debuggable {
|
|||||||
let currentOffset = 0;
|
let currentOffset = 0;
|
||||||
for (const car of this.cars) {
|
for (const car of this.cars) {
|
||||||
// This needs to be moved to the car itself
|
// This needs to be moved to the car itself
|
||||||
if (!car.points) return;
|
// if (!car.points) return;
|
||||||
const [a, b] = car.points;
|
// const [a, b] = car.points;
|
||||||
const nA = this.path.followEvenPoints(this.t - currentOffset);
|
// const nA = this.path.followEvenPoints(this.t - currentOffset);
|
||||||
a.set(nA.p);
|
// a.set(nA.p);
|
||||||
currentOffset += car.length;
|
// currentOffset += car.length;
|
||||||
const nB = this.path.followEvenPoints(this.t - currentOffset);
|
// const nB = this.path.followEvenPoints(this.t - currentOffset);
|
||||||
b.set(nB.p);
|
// b.set(nB.p);
|
||||||
currentOffset += this.spacing;
|
// currentOffset += this.spacing;
|
||||||
car.segments = [nA.segmentId, nB.segmentId];
|
// car.segments = [nA.segmentId, nB.segmentId];
|
||||||
// car.draw();
|
// car.draw();
|
||||||
|
|
||||||
|
currentOffset += car.moveAlongPath(this.t - currentOffset) + this.spacing;
|
||||||
}
|
}
|
||||||
// this.draw();
|
// this.draw();
|
||||||
}
|
}
|
||||||
@ -118,7 +121,7 @@ export class Train extends Debuggable {
|
|||||||
colors.push(colors.shift()!);
|
colors.push(colors.shift()!);
|
||||||
colors.push(colors.shift()!);
|
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);
|
const segment = track.getSegment(segmentId);
|
||||||
segment &&
|
segment &&
|
||||||
doodler.drawBezier(...segment.points, {
|
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 {
|
export class TrainCar extends Debuggable {
|
||||||
img: HTMLImageElement;
|
img: HTMLImageElement;
|
||||||
imgWidth: number;
|
imgWidth: number;
|
||||||
@ -143,10 +152,15 @@ export class TrainCar extends Debuggable {
|
|||||||
points?: [Vector, Vector, ...Vector[]];
|
points?: [Vector, Vector, ...Vector[]];
|
||||||
length: number;
|
length: number;
|
||||||
|
|
||||||
segments: string[] = [];
|
bogies: Bogie[] = [];
|
||||||
|
|
||||||
|
segments: Set<string> = new Set();
|
||||||
|
|
||||||
|
train?: Train;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
length: number,
|
length: number,
|
||||||
|
trailing: number,
|
||||||
img: HTMLImageElement,
|
img: HTMLImageElement,
|
||||||
w: number,
|
w: number,
|
||||||
h: number,
|
h: number,
|
||||||
@ -158,14 +172,51 @@ export class TrainCar extends Debuggable {
|
|||||||
this.imgWidth = w;
|
this.imgWidth = w;
|
||||||
this.imgHeight = h;
|
this.imgHeight = h;
|
||||||
this.length = length;
|
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() {
|
draw() {
|
||||||
if (!this.points) return;
|
|
||||||
const doodler = getContextItem<Doodler>("doodler");
|
const doodler = getContextItem<Doodler>("doodler");
|
||||||
const [a, b] = this.points;
|
const [a, b] = this.bogies;
|
||||||
const origin = Vector.add(Vector.sub(a, b).div(2), b);
|
const origin = Vector.add(Vector.sub(a.pos, b.pos).div(2), b.pos);
|
||||||
const angle = Vector.sub(b, a).heading();
|
const angle = Vector.sub(b.pos, a.pos).heading();
|
||||||
|
|
||||||
doodler.drawCircle(origin, 4, { color: "blue" });
|
doodler.drawCircle(origin, 4, { color: "blue" });
|
||||||
|
|
||||||
@ -187,11 +238,19 @@ export class TrainCar extends Debuggable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
override debugDraw(...args: unknown[]): void {
|
override debugDraw(...args: unknown[]): void {
|
||||||
if (!this.points) return;
|
|
||||||
const doodler = getContextItem<Doodler>("doodler");
|
const doodler = getContextItem<Doodler>("doodler");
|
||||||
doodler.drawLine(this.points, {
|
doodler.drawLine(this.bogies.map((b) => b.pos), {
|
||||||
color: "blue",
|
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