track drawing and shape tweaks, train controls, fps counter, non-looping
This commit is contained in:
@@ -13,20 +13,26 @@ export class StraightTrack extends TrackSegment {
|
||||
}
|
||||
}
|
||||
|
||||
export class SBendLeft extends StraightTrack {
|
||||
export class SBendLeft extends TrackSegment {
|
||||
constructor(start?: Vector) {
|
||||
start = start || new Vector(100, 100);
|
||||
super(start);
|
||||
this.points[2].add(0, -25);
|
||||
this.points[3].add(0, -25);
|
||||
super([
|
||||
start,
|
||||
start.copy().add(60, 0),
|
||||
start.copy().add(90, -25),
|
||||
start.copy().add(150, -25),
|
||||
]);
|
||||
}
|
||||
}
|
||||
export class SBendRight extends StraightTrack {
|
||||
export class SBendRight extends TrackSegment {
|
||||
constructor(start?: Vector) {
|
||||
start = start || new Vector(100, 100);
|
||||
super(start);
|
||||
this.points[2].add(0, 25);
|
||||
this.points[3].add(0, 25);
|
||||
super([
|
||||
start,
|
||||
start.copy().add(60, 0),
|
||||
start.copy().add(90, 25),
|
||||
start.copy().add(150, 25),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
118
track/system.ts
118
track/system.ts
@@ -1,6 +1,7 @@
|
||||
import { Doodler, Point, Vector } from "@bearmetal/doodler";
|
||||
import { ComplexPath, PathSegment } from "../math/path.ts";
|
||||
import { getContextItem, setDefaultContext } from "../lib/context.ts";
|
||||
import { clamp } from "../math/clamp.ts";
|
||||
|
||||
export class TrackSystem {
|
||||
private segments: Map<string, TrackSegment> = new Map();
|
||||
@@ -34,7 +35,7 @@ export class TrackSystem {
|
||||
}
|
||||
|
||||
draw(showControls = false) {
|
||||
for (const segment of this.segments.values()) {
|
||||
for (const [i, segment] of this.segments.entries()) {
|
||||
segment.draw(showControls);
|
||||
}
|
||||
|
||||
@@ -232,8 +233,6 @@ export class TrackSegment extends PathSegment {
|
||||
|
||||
doodler: Doodler;
|
||||
|
||||
id: string;
|
||||
|
||||
constructor(p: VectorSet, id?: string) {
|
||||
super(p);
|
||||
this.doodler = getContextItem<Doodler>("doodler");
|
||||
@@ -245,29 +244,82 @@ export class TrackSegment extends PathSegment {
|
||||
}
|
||||
|
||||
override draw(showControls = false) {
|
||||
this.doodler.drawBezier(
|
||||
this.points[0],
|
||||
this.points[1],
|
||||
this.points[2],
|
||||
this.points[3],
|
||||
{
|
||||
strokeColor: "#ffffff50",
|
||||
},
|
||||
);
|
||||
// if (showControls) {
|
||||
// this.doodler.drawBezier(
|
||||
// this.points[0],
|
||||
// this.points[1],
|
||||
// this.points[2],
|
||||
// this.points[3],
|
||||
// {
|
||||
// strokeColor: "#ffffff50",
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
if (showControls) {
|
||||
this.doodler.fillCircle(this.points[0], 1, {
|
||||
color: "red",
|
||||
});
|
||||
this.doodler.fillCircle(this.points[1], 1, {
|
||||
color: "red",
|
||||
});
|
||||
this.doodler.fillCircle(this.points[2], 1, {
|
||||
color: "red",
|
||||
});
|
||||
this.doodler.fillCircle(this.points[3], 1, {
|
||||
color: "red",
|
||||
this.doodler.deferDrawing(() => {
|
||||
this.doodler.fillCircle(this.points[0], 1, {
|
||||
color: "red",
|
||||
});
|
||||
this.doodler.fillCircle(this.points[1], 1, {
|
||||
color: "red",
|
||||
});
|
||||
this.doodler.fillCircle(this.points[2], 1, {
|
||||
color: "red",
|
||||
});
|
||||
this.doodler.fillCircle(this.points[3], 1, {
|
||||
color: "red",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const ties = Math.ceil(this.length / 10);
|
||||
for (let i = 0; i < ties; i++) {
|
||||
const t = i / ties;
|
||||
const p = this.getPointAtT(t);
|
||||
// this.doodler.drawCircle(p, 2, {
|
||||
// color: "red",
|
||||
// weight: 3,
|
||||
// });
|
||||
this.doodler.drawRotated(p, this.tangent(t).heading(), () => {
|
||||
this.doodler.line(p, p.copy().add(0, 10), {
|
||||
color: "#291b17",
|
||||
weight: 4,
|
||||
});
|
||||
this.doodler.line(p, p.copy().add(0, -10), {
|
||||
color: "#291b17",
|
||||
weight: 4,
|
||||
});
|
||||
// this.doodler.line(p.copy().add(-6, 5), p.copy().add(6, 5), {
|
||||
// color: "grey",
|
||||
// weight: 1,
|
||||
// });
|
||||
// this.doodler.line(p.copy().add(-6, -5), p.copy().add(6, -5), {
|
||||
// color: "grey",
|
||||
// weight: 1,
|
||||
// });
|
||||
});
|
||||
}
|
||||
const lineResolution = 100;
|
||||
const normalPoints: Vector[] = [];
|
||||
const antiNormalPoints: Vector[] = [];
|
||||
for (let i = 0; i <= lineResolution; i++) {
|
||||
const t = i / lineResolution;
|
||||
const normal = this.tangent(t).rotate(Math.PI / 2);
|
||||
normal.setMag(6);
|
||||
const p = this.getPointAtT(t);
|
||||
normalPoints.push(p.copy().add(normal));
|
||||
antiNormalPoints.push(p.copy().add(normal.rotate(Math.PI)));
|
||||
}
|
||||
this.doodler.deferDrawing(
|
||||
() => {
|
||||
this.doodler.drawLine(normalPoints, { color: "grey" });
|
||||
this.doodler.drawLine(antiNormalPoints, { color: "grey" });
|
||||
},
|
||||
);
|
||||
// this.doodler.drawCircle(p, 2, {
|
||||
// color: "red",
|
||||
// weight: 3,
|
||||
// });
|
||||
}
|
||||
|
||||
serialize(): SerializedTrackSegment {
|
||||
@@ -382,6 +434,8 @@ export class Spline<T extends PathSegment = PathSegment> {
|
||||
|
||||
nodes: IControlNode[];
|
||||
|
||||
looped = false;
|
||||
|
||||
constructor(segs: T[]) {
|
||||
this.segments = segs;
|
||||
this.pointSpacing = 1;
|
||||
@@ -452,10 +506,20 @@ export class Spline<T extends PathSegment = PathSegment> {
|
||||
}
|
||||
|
||||
followEvenPoints(t: number) {
|
||||
if (t < 0) t += this.evenPoints.length;
|
||||
const i = Math.floor(t) % this.evenPoints.length;
|
||||
const a = this.evenPoints[i];
|
||||
const b = this.evenPoints[(i + 1) % this.evenPoints.length];
|
||||
if (this.looped) {
|
||||
if (t < 0) t += this.evenPoints.length;
|
||||
const i = Math.floor(t) % this.evenPoints.length;
|
||||
const a = this.evenPoints[i];
|
||||
const b = this.evenPoints[(i + 1) % this.evenPoints.length];
|
||||
return Vector.lerp(a, b, t % 1);
|
||||
}
|
||||
t = clamp(t, 0, this.evenPoints.length - 1);
|
||||
const i = clamp(Math.floor(t), 0, this.evenPoints.length - 1);
|
||||
const a = this.evenPoints[clamp(i, 0, this.evenPoints.length - 1)];
|
||||
const b = this
|
||||
.evenPoints[
|
||||
clamp((i + 1) % this.evenPoints.length, 0, this.evenPoints.length - 1)
|
||||
];
|
||||
return Vector.lerp(a, b, t % 1);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user