diff --git a/src/lib/context.ts b/src/lib/context.ts index 700771e..7cf895b 100644 --- a/src/lib/context.ts +++ b/src/lib/context.ts @@ -1,4 +1,6 @@ import { TrackSegment } from "../track/system.ts"; +import { Train, TrainCar } from "../train/train.ts"; +import { InputManager } from "./input.ts"; type ContextStore = Record; @@ -85,33 +87,59 @@ if (debug) { function safeStringify(obj: any) { const seen = new WeakSet(); return JSON.stringify(obj, (key, value) => { - if (value instanceof Map) { - const val: Record = {}; - for (const [k, v] of value) { - if (typeof k !== "string") continue; - val[k] = v; - } - return val; - } - - if (value instanceof Set) { - return Array.from(value); - } - - if (value instanceof TrackSegment) { - return { - ...value, - frontNeighbours: value.frontNeighbours.map((n) => n.id), - backNeighbours: value.backNeighbours.map((n) => n.id), - }; - } - if (typeof value === "object" && value !== null) { if (seen.has(value)) { return "[Circular]"; // Replace circular references } seen.add(value); } + if (value instanceof Map) { + const val: Record = {}; + for (const [k, v] of value) { + if (typeof k !== "string") continue; + val[k] = v; + } + seen.add(value); + return val; + } + + if (value instanceof Set) { + seen.add(value); + value = Array.from(value); + return value; + } + + if (value instanceof TrackSegment) { + seen.add(value); + const val = { ...value }; + (val as any).frontNeighbours = value.frontNeighbours.map((n) => n.id); + (val as any).backNeighbours = value.backNeighbours.map((n) => n.id); + return val; + } + + // if (value instanceof Train) { + // const val = { ...value }; + // // val.segments = value.segments.map((s) => s.id); + // delete (val as any).path; + // delete (val as any).nodes; + // delete (val as any).cars; + // delete (val as any).t; + + // // val.t + // // val. + // return null; + // } + + // if (value instanceof InputManager) { + // return {}; + // } + + // if (value instanceof TrainCar) { + // const val = { ...value }; + + // return val; + // } + return value; }, 2); } diff --git a/src/main.ts b/src/main.ts index dd33d00..cd1a780 100644 --- a/src/main.ts +++ b/src/main.ts @@ -24,7 +24,7 @@ const doodler = new ZoomableDoodler({ (doodler as any as { ctx: CanvasRenderingContext2D }).ctx .imageSmoothingEnabled = false; // doodler.minScale = 0.1; -// (doodler as any).scale = doodler.maxScale; +(doodler as any).scale = 3.14; const colors = [ "red", @@ -41,7 +41,11 @@ setDefaultContext({ inputManager, doodler, resources, - debug: false, + debug: { + track: false, + train: false, + path: false, + }, colors, }); diff --git a/src/track/system.ts b/src/track/system.ts index e49fc97..f20fc75 100644 --- a/src/track/system.ts +++ b/src/track/system.ts @@ -4,33 +4,37 @@ import { getContextItem, setDefaultContext } from "../lib/context.ts"; import { clamp } from "../math/clamp.ts"; export class TrackSystem { - private segments: Map = new Map(); + private _segments: Map = new Map(); private doodler: Doodler; constructor(segments: TrackSegment[]) { this.doodler = getContextItem("doodler"); for (const segment of segments) { - this.segments.set(segment.id, segment); + this._segments.set(segment.id, segment); } } + getSegment(id: string) { + return this._segments.get(id); + } + get firstSegment() { - return this.segments.values().next().value; + return this._segments.values().next().value; } get lastSegment() { - return this.segments.values().toArray().pop(); + return this._segments.values().toArray().pop(); } optimize(percent: number) { console.log("Optimizing track", percent * 100 / 4); - for (const segment of this.segments.values()) { + for (const segment of this._segments.values()) { segment.recalculateRailPoints(Math.round(percent * 100 / 4)); } } recalculateAll() { - for (const segment of this.segments.values()) { + for (const segment of this._segments.values()) { segment.recalculateRailPoints(); segment.length = segment.calculateApproxLength(); } @@ -38,11 +42,11 @@ export class TrackSystem { registerSegment(segment: TrackSegment) { segment.setTrack(this); - this.segments.set(segment.id, segment); + this._segments.set(segment.id, segment); } unregisterSegment(segment: TrackSegment) { - this.segments.delete(segment.id); - for (const s of this.segments.values()) { + this._segments.delete(segment.id); + for (const s of this._segments.values()) { s.backNeighbours = s.backNeighbours.filter((n) => n !== segment); s.frontNeighbours = s.frontNeighbours.filter((n) => n !== segment); } @@ -52,7 +56,7 @@ export class TrackSystem { } draw(showControls = false) { - for (const [i, segment] of this.segments.entries()) { + for (const [i, segment] of this._segments.entries()) { segment.draw(showControls); } @@ -85,7 +89,7 @@ export class TrackSystem { endArray: End[] = []; findEnds() { - for (const segment of this.segments.values()) { + for (const segment of this._segments.values()) { if (this.ends.has(segment)) continue; const ends: [End, End] = [ { @@ -109,14 +113,14 @@ export class TrackSystem { serialize() { return JSON.stringify( - this.segments.values().map((s) => s.serialize()).toArray(), + this._segments.values().map((s) => s.serialize()).toArray(), ); } copy() { const track = new TrackSystem([]); - for (const segment of this.segments.values()) { - track.segments.set(segment.id, segment.copy()); + for (const segment of this._segments.values()) { + track._segments.set(segment.id, segment.copy()); } return track; } @@ -127,19 +131,19 @@ export class TrackSystem { const neighborMap = new Map(); for (const segment of data) { - track.segments.set(segment.id, TrackSegment.deserialize(segment)); + track._segments.set(segment.id, TrackSegment.deserialize(segment)); neighborMap.set(segment.id, [segment.fNeighbors, segment.bNeighbors]); } - for (const segment of track.segments.values()) { + for (const segment of track._segments.values()) { segment.setTrack(track); const neighbors = neighborMap.get(segment.id); if (neighbors) { segment.backNeighbours = neighbors[1].map((id) => - track.segments.get(id) + track._segments.get(id) ).filter((s) => s) as TrackSegment[]; segment.frontNeighbours = neighbors[0].map((id) => - track.segments.get(id) + track._segments.get(id) ).filter((s) => s) as TrackSegment[]; } } @@ -148,7 +152,7 @@ export class TrackSystem { } translate(v: Vector) { - for (const segment of this.segments.values()) { + for (const segment of this._segments.values()) { segment.translate(v); } } diff --git a/src/train/train.ts b/src/train/train.ts index 4b50384..b7340b8 100644 --- a/src/train/train.ts +++ b/src/train/train.ts @@ -3,7 +3,7 @@ import { Follower } from "../physics/follower.ts"; import { Mover } from "../physics/mover.ts"; import { getContext, getContextItem } from "../lib/context.ts"; import { Doodler, Vector } from "@bearmetal/doodler"; -import { Spline, TrackSegment } from "../track/system.ts"; +import { Spline, TrackSegment, TrackSystem } from "../track/system.ts"; import { ResourceManager } from "../lib/resources.ts"; import { map } from "../math/lerp.ts"; @@ -107,9 +107,9 @@ export class Train { // } draw() { - const ctx = getContext(); - if (ctx.debug) { - const doodler = getContextItem("doodler"); + const debug = getContextItem("debug"); + const doodler = getContextItem("doodler"); + if (debug.path) { // doodler.drawLine(this.path.points, { // color: "red", // weight: 3, @@ -124,6 +124,16 @@ export class Train { doodler.drawCircle(p.p, 2, { color, weight: .5 }); } } + + if (debug.train) { + const track = getContextItem("track"); + for (const segmentId of this.segments) { + const segment = track.getSegment(segmentId); + segment && + doodler.drawBezier(...segment.points, { color: "red", weight: 3 }); + } + } + for (const car of this.cars) { car.draw(); } @@ -185,8 +195,8 @@ export class TrainCar { ); }); - const ctx = getContext(); - if (ctx.debug) { + const debug = getContextItem("debug"); + if (debug.car) { doodler.drawLine(this.points, { color: "blue", weight: 3, diff --git a/src/types.ts b/src/types.ts index fac5991..c088a1b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,4 +15,11 @@ declare global { bNeighbors: string[]; fNeighbors: string[]; }; + + type Debug = { + track: boolean; + train: boolean; + car: boolean; + path: boolean; + }; }