migrate to vite working
This commit is contained in:
420
src/state/states/EditTrackState.ts
Normal file
420
src/state/states/EditTrackState.ts
Normal file
@@ -0,0 +1,420 @@
|
||||
import { Doodler, Vector } from "@bearmetal/doodler";
|
||||
import {
|
||||
getContextItem,
|
||||
getContextItemOrDefault,
|
||||
setContextItem,
|
||||
} from "../../lib/context.ts";
|
||||
import { InputManager } from "../../lib/input.ts";
|
||||
import { TrackSystem } from "../../track/system.ts";
|
||||
import { State, StateMachine } from "../machine.ts";
|
||||
import { States } from "./index.ts";
|
||||
import {
|
||||
BankLeft,
|
||||
BankRight,
|
||||
SBendLeft,
|
||||
SBendRight,
|
||||
StraightTrack,
|
||||
} from "../../track/shapes.ts";
|
||||
import { TrackSegment } from "../../track/system.ts";
|
||||
import { clamp } from "../../math/clamp.ts";
|
||||
|
||||
export class EditTrackState extends State<States> {
|
||||
override name: States = States.EDIT_TRACK;
|
||||
override validTransitions: Set<States> = new Set([
|
||||
States.RUNNING,
|
||||
States.PAUSED,
|
||||
]);
|
||||
|
||||
private heldEvents: Map<string, (() => void) | undefined> = new Map();
|
||||
|
||||
private currentSegment?: TrackSegment;
|
||||
private selectedSegment?: TrackSegment;
|
||||
private ghostSegment?: TrackSegment;
|
||||
private ghostRotated = false;
|
||||
private closestEnd?: End;
|
||||
|
||||
layers: number[] = [];
|
||||
|
||||
override update(dt: number): void {
|
||||
const inputManager = getContextItem<InputManager>("inputManager");
|
||||
const track = getContextItem<TrackSystem>("track");
|
||||
const doodler = getContextItem<Doodler>("doodler");
|
||||
|
||||
// For moving a segment, i.e. the currently active one
|
||||
// const segment = track.lastSegment;
|
||||
// if (segment) {
|
||||
// const firstPoint = segment.points[0].copy();
|
||||
// const { x, y } = inputManager.getMouseLocation();
|
||||
// segment.points.forEach((p, i) => {
|
||||
// const relativePoint = Vector.sub(p, firstPoint);
|
||||
// p.set(x, y);
|
||||
// p.add(relativePoint);
|
||||
// });
|
||||
// }
|
||||
|
||||
if (this.selectedSegment) {
|
||||
const segment = this.selectedSegment;
|
||||
const firstPoint = segment.points[0].copy();
|
||||
const mousePos = inputManager.getMouseLocationV();
|
||||
segment.points.forEach((p, i) => {
|
||||
const relativePoint = Vector.sub(p, firstPoint);
|
||||
p.set(mousePos);
|
||||
p.add(relativePoint);
|
||||
});
|
||||
|
||||
const ends = track.findEnds();
|
||||
setContextItem("showEnds", true);
|
||||
const nearbyEnds = ends.filter((end) => {
|
||||
const dist = Vector.dist(end.pos, mousePos);
|
||||
return dist < 20 && end.segment !== segment;
|
||||
});
|
||||
let closestEnd = nearbyEnds[0];
|
||||
for (const end of nearbyEnds) {
|
||||
if (end === closestEnd) continue;
|
||||
const closestEndTangent = Vector.add(
|
||||
closestEnd.tangent.copy().mult(20),
|
||||
closestEnd.pos,
|
||||
);
|
||||
const endTangent = Vector.add(
|
||||
end.tangent.copy().rotate(Math.PI).mult(20),
|
||||
end.pos,
|
||||
);
|
||||
doodler.drawCircle(closestEndTangent, 4, { color: "red", weight: 1 });
|
||||
doodler.drawCircle(endTangent, 4, { color: "blue", weight: 1 });
|
||||
if (
|
||||
endTangent.dist(mousePos) < closestEndTangent.dist(mousePos) ||
|
||||
end.pos.dist(mousePos) < closestEnd.pos.dist(mousePos)
|
||||
) {
|
||||
closestEnd = end;
|
||||
}
|
||||
}
|
||||
if (closestEnd !== this.closestEnd) {
|
||||
this.closestEnd = closestEnd;
|
||||
this.ghostSegment = undefined;
|
||||
this.ghostRotated = false;
|
||||
}
|
||||
if (closestEnd) {
|
||||
// doodler.drawCircle(closestEnd.pos, 4, { color: "green", weight: 1 });
|
||||
doodler.line(
|
||||
closestEnd.pos,
|
||||
Vector.add(closestEnd.pos, closestEnd.tangent.copy().mult(20)),
|
||||
{ color: "green" },
|
||||
);
|
||||
}
|
||||
if (
|
||||
this.closestEnd
|
||||
) {
|
||||
if (!this.ghostSegment) {
|
||||
this.ghostSegment = segment.copy();
|
||||
this.ghostRotated = false;
|
||||
}
|
||||
switch (this.closestEnd.frontOrBack) {
|
||||
case "front":
|
||||
this.ghostSegment.setPositionByPoint(
|
||||
this.closestEnd.pos,
|
||||
this.ghostSegment.points[0],
|
||||
);
|
||||
// this.ghostSegment.points[0] = this.closestEnd.pos;
|
||||
!this.ghostRotated && this.ghostSegment.rotateAboutPoint(
|
||||
this.closestEnd.tangent.heading(),
|
||||
this.ghostSegment.points[0],
|
||||
);
|
||||
this.ghostRotated = true;
|
||||
break;
|
||||
case "back": {
|
||||
this.ghostSegment.setPositionByPoint(
|
||||
this.closestEnd.pos,
|
||||
this.ghostSegment.points[3],
|
||||
);
|
||||
const ghostEndTangent = this.ghostSegment.tangent(1);
|
||||
// this.ghostSegment.points[3] = this.closestEnd.pos;
|
||||
!this.ghostRotated && this.ghostSegment.rotateAboutPoint(
|
||||
this.closestEnd.tangent.heading() - ghostEndTangent.heading(),
|
||||
this.ghostSegment.points[3],
|
||||
);
|
||||
this.ghostRotated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// } else if (closestEnd) {
|
||||
// this.closestEnd = closestEnd;
|
||||
} else if (!this.closestEnd || !closestEnd) {
|
||||
this.ghostSegment = undefined;
|
||||
this.ghostRotated = false;
|
||||
}
|
||||
}
|
||||
|
||||
// manipulate only end of segment while maintaining length
|
||||
// const segment = track.lastSegment;
|
||||
// if (segment) {
|
||||
// const p3 = segment.points[2];
|
||||
// const p4 = segment.points[3];
|
||||
// let curveLength = Math.round(segment.calculateApproxLength());
|
||||
// this.startingLength = this.startingLength ?? curveLength;
|
||||
// curveLength = this.startingLength;
|
||||
// const { x, y } = inputManager.getMouseLocation();
|
||||
// p4.set(x, y);
|
||||
// const points = segment.calculateEvenlySpacedPoints(1);
|
||||
// if (points.length > curveLength) p4.set(points[curveLength - 1]);
|
||||
|
||||
// // doodler.fillText(curveLength.toFixed(2), p3.copy().add(10, 0), 100);
|
||||
// }
|
||||
|
||||
// Adjust angles until tangent points to mouse
|
||||
// const segment = this.currentSegment;
|
||||
// if (segment) {
|
||||
// segment.propagate();
|
||||
|
||||
// const mousePos = inputManager.getMouseLocationV();
|
||||
// const p1 = segment.points[0];
|
||||
// const p2 = segment.points[1];
|
||||
// const p3 = segment.points[2];
|
||||
// const p4 = segment.points[3];
|
||||
|
||||
// const prevp3 = p3.copy();
|
||||
// const dirToMouse = Vector.sub(mousePos, p2).normalize();
|
||||
// const angleToMouse = dirToMouse.heading();
|
||||
// const dirToP1 = Vector.sub(p2, p1).normalize();
|
||||
// const angleToP1 = dirToP1.heading();
|
||||
// const p2DistToMouse = Vector.dist(p2, mousePos);
|
||||
// const p3DistToMouse = Vector.dist(p3, mousePos);
|
||||
// const distToP3 = Vector.dist(p2, p3);
|
||||
// const distToP4 = Vector.dist(prevp3, p4);
|
||||
|
||||
// const goodangle = clamp(
|
||||
// angleToMouse - angleToP1,
|
||||
// angleToP1 - .6,
|
||||
// angleToP1 + .6,
|
||||
// );
|
||||
// if (
|
||||
// // Math.abs(goodangle) < .6 &&
|
||||
// p2DistToMouse > distToP3 &&
|
||||
// p3DistToMouse > distToP4
|
||||
// ) {
|
||||
// {
|
||||
// const dirToNewP3 = dirToP1.copy().rotate(
|
||||
// goodangle / 2,
|
||||
// );
|
||||
// dirToNewP3.setMag(distToP3);
|
||||
// p3.set(Vector.add(p2, dirToNewP3));
|
||||
// doodler.line(p2, Vector.add(p2, dirToNewP3), { color: "blue" });
|
||||
// doodler.line(
|
||||
// p2,
|
||||
// Vector.add(p2, dirToNewP3),
|
||||
// {
|
||||
// color: "red",
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
// {
|
||||
// const dirToMouse = Vector.sub(mousePos, p3).normalize();
|
||||
// const dirToP3 = Vector.sub(p3, p2).normalize();
|
||||
// const angleToP3 = dirToP3.heading();
|
||||
// const goodangle = clamp(
|
||||
// dirToMouse.heading() - angleToP3,
|
||||
// angleToP3 - .6,
|
||||
// angleToP3 + .6,
|
||||
// );
|
||||
|
||||
// const dirToNewP4 = dirToP3.copy().rotate(
|
||||
// goodangle / 2,
|
||||
// );
|
||||
// dirToNewP4.setMag(distToP4);
|
||||
// p4.set(Vector.add(p3, dirToNewP4));
|
||||
// doodler.line(p3, Vector.add(p3, dirToNewP4), { color: "green" });
|
||||
// }
|
||||
// segment.clampLength();
|
||||
// }
|
||||
// // doodler.fillText(
|
||||
// // segment.calculateApproxLength().toFixed(2),
|
||||
// // p2.copy().add(10, 0),
|
||||
// // 100,
|
||||
// // );
|
||||
// }
|
||||
|
||||
const translation = new Vector(0, 0);
|
||||
|
||||
if (inputManager.getKeyState("ArrowUp")) {
|
||||
translation.y -= 1;
|
||||
}
|
||||
if (inputManager.getKeyState("ArrowDown")) {
|
||||
translation.y += 1;
|
||||
}
|
||||
if (inputManager.getKeyState("ArrowLeft")) {
|
||||
translation.x -= 1;
|
||||
}
|
||||
if (inputManager.getKeyState("ArrowRight")) {
|
||||
translation.x += 1;
|
||||
}
|
||||
|
||||
if (translation.x !== 0 || translation.y !== 0) {
|
||||
track.translate(translation);
|
||||
}
|
||||
|
||||
// TODO
|
||||
// Draw ui
|
||||
// Draw track points
|
||||
// Draw track tangents
|
||||
}
|
||||
override start(): void {
|
||||
const doodler = getContextItem<Doodler>("doodler");
|
||||
this.layers.push(
|
||||
doodler.createLayer(() => {
|
||||
this.selectedSegment?.draw(false, true);
|
||||
if (this.ghostSegment) {
|
||||
doodler.drawWithAlpha(0.5, () => {
|
||||
if (!this.ghostSegment) return;
|
||||
this.ghostSegment.draw(false, true);
|
||||
if (getContextItemOrDefault("debug", false)) {
|
||||
const colors = getContextItem<string[]>("colors");
|
||||
for (
|
||||
const [i, point] of this.ghostSegment.points.entries() ?? []
|
||||
) {
|
||||
doodler.fillCircle(point, 4, { color: colors[i + 3] });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
track.draw(true);
|
||||
}),
|
||||
);
|
||||
|
||||
setContextItem("trackSegments", [
|
||||
undefined,
|
||||
new StraightTrack(),
|
||||
new SBendLeft(),
|
||||
new SBendRight(),
|
||||
new BankLeft(),
|
||||
new BankRight(),
|
||||
]);
|
||||
|
||||
const inputManager = getContextItem<InputManager>("inputManager");
|
||||
this.heldEvents.set("e", inputManager.offKey("e"));
|
||||
this.heldEvents.set("Escape", inputManager.offKey("Escape"));
|
||||
inputManager.onKey("e", () => {
|
||||
const state = getContextItem<StateMachine<States>>("state");
|
||||
state.transitionTo(States.RUNNING);
|
||||
});
|
||||
|
||||
const track = getContextItem<TrackSystem>("track");
|
||||
setContextItem("trackCopy", track.copy());
|
||||
inputManager.onKey("Escape", () => {
|
||||
const trackCopy = getContextItem<TrackSystem>("trackCopy");
|
||||
setContextItem("track", trackCopy);
|
||||
setContextItem("trackCopy", undefined);
|
||||
const state = getContextItem<StateMachine<States>>("state");
|
||||
state.transitionTo(States.RUNNING);
|
||||
});
|
||||
|
||||
inputManager.onKey(" ", () => {
|
||||
if (this.selectedSegment) {
|
||||
this.selectedSegment = undefined;
|
||||
} else {
|
||||
this.selectedSegment = new StraightTrack();
|
||||
}
|
||||
});
|
||||
|
||||
inputManager.onMouse("left", () => {
|
||||
const track = getContextItem<TrackSystem>("track");
|
||||
if (this.ghostSegment && this.closestEnd) {
|
||||
const segment = this.ghostSegment.cleanCopy();
|
||||
|
||||
switch (this.closestEnd.frontOrBack) {
|
||||
case "front":
|
||||
this.closestEnd.segment.frontNeighbours.push(segment);
|
||||
segment.backNeighbours.push(this.closestEnd.segment);
|
||||
break;
|
||||
case "back":
|
||||
this.closestEnd.segment.backNeighbours.push(segment);
|
||||
segment.frontNeighbours.push(this.closestEnd.segment);
|
||||
break;
|
||||
}
|
||||
track.registerSegment(segment);
|
||||
this.ghostSegment = undefined;
|
||||
this.closestEnd = undefined;
|
||||
} else if (this.selectedSegment) {
|
||||
track.registerSegment(this.selectedSegment.cleanCopy());
|
||||
// this.selectedSegment = new StraightTrack();
|
||||
} else {
|
||||
this.selectedSegment = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
// inputManager.onKey("w", () => {
|
||||
// const track = getContextItem<TrackSystem>("track");
|
||||
// const segment = track.lastSegment;
|
||||
// if (!segment) return;
|
||||
// const n = new StraightTrack(segment.points[3]);
|
||||
// const t = segment.tangent(1).heading();
|
||||
// n.rotate(t);
|
||||
// segment.frontNeighbours.push(n);
|
||||
// track.registerSegment(n);
|
||||
// this.currentSegment = n;
|
||||
// });
|
||||
|
||||
// inputManager.onKey("1", () => {
|
||||
// this.currentSegment = track.firstSegment;
|
||||
// });
|
||||
|
||||
inputManager.onNumberKey((i) => {
|
||||
const segments = getContextItem<TrackSegment[]>("trackSegments");
|
||||
this.selectedSegment = segments[i];
|
||||
this.ghostRotated = false;
|
||||
this.ghostSegment = undefined;
|
||||
});
|
||||
|
||||
// this.currentSegment = track.lastSegment;
|
||||
inputManager.onKey("z", () => {
|
||||
if (inputManager.getKeyState("Control")) {
|
||||
const segment = track.lastSegment;
|
||||
if (!segment) return;
|
||||
this.redoBuffer.push(segment);
|
||||
if (this.redoBuffer.length > 100) {
|
||||
this.redoBuffer.shift();
|
||||
}
|
||||
track.unregisterSegment(segment);
|
||||
}
|
||||
});
|
||||
inputManager.onKey("y", () => {
|
||||
if (inputManager.getKeyState("Control")) {
|
||||
const segment = this.redoBuffer.pop();
|
||||
if (!segment) return;
|
||||
track.registerSegment(segment);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO
|
||||
// Cache trains and save
|
||||
|
||||
// const trackCount = 2000;
|
||||
// for (let i = 0; i < trackCount; i++) {
|
||||
// const seg = new StraightTrack();
|
||||
// track.registerSegment(seg);
|
||||
// }
|
||||
}
|
||||
redoBuffer: TrackSegment[] = [];
|
||||
override stop(): void {
|
||||
for (const layer of this.layers) {
|
||||
getContextItem<Doodler>("doodler").deleteLayer(layer);
|
||||
}
|
||||
|
||||
const track = getContextItem<TrackSystem>("track");
|
||||
track.recalculateAll();
|
||||
|
||||
const inputManager = getContextItem<InputManager>("inputManager");
|
||||
inputManager.offKey("e");
|
||||
inputManager.offKey("w");
|
||||
inputManager.offKey("Escape");
|
||||
inputManager.offMouse("left");
|
||||
if (this.heldEvents.size > 0) {
|
||||
for (const [key, cb] of this.heldEvents) {
|
||||
if (cb) {
|
||||
getContextItem<InputManager>("inputManager").onKey(key, cb);
|
||||
}
|
||||
this.heldEvents.delete(key);
|
||||
}
|
||||
}
|
||||
setContextItem("trackCopy", undefined);
|
||||
setContextItem("trackSegments", undefined);
|
||||
}
|
||||
}
|
25
src/state/states/EditTrainState.ts
Normal file
25
src/state/states/EditTrainState.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { State } from "../machine.ts";
|
||||
import { States } from "./index.ts";
|
||||
|
||||
export class EditTrainState extends State<States> {
|
||||
override name: States = States.EDIT_TRAIN;
|
||||
override validTransitions: Set<States> = new Set([
|
||||
States.RUNNING,
|
||||
States.PAUSED,
|
||||
]);
|
||||
|
||||
override update(dt: number): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
override start(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
// TODO
|
||||
// Cache trains
|
||||
// Stash train in context
|
||||
// Draw track
|
||||
// Draw train (filtered by train ID)
|
||||
}
|
||||
override stop(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
67
src/state/states/LoadState.ts
Normal file
67
src/state/states/LoadState.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Doodler, Vector } from "@bearmetal/doodler";
|
||||
import { bootstrapInputs } from "../../inputs.ts";
|
||||
import { getContextItem, setContextItem } from "../../lib/context.ts";
|
||||
import { InputManager } from "../../lib/input.ts";
|
||||
import { ResourceManager } from "../../lib/resources.ts";
|
||||
import { StraightTrack } from "../../track/shapes.ts";
|
||||
import { TrackSystem } from "../../track/system.ts";
|
||||
import { State } from "../machine.ts";
|
||||
import { States } from "./index.ts";
|
||||
|
||||
export class LoadState extends State<States> {
|
||||
override name: States = States.LOAD;
|
||||
override validTransitions: Set<States> = new Set([
|
||||
States.RUNNING,
|
||||
]);
|
||||
|
||||
layers: number[] = [];
|
||||
|
||||
override update(): void {
|
||||
// noop
|
||||
}
|
||||
override start(): void {
|
||||
const track = this.loadTrack() ?? new TrackSystem([new StraightTrack()]);
|
||||
setContextItem("track", track);
|
||||
|
||||
const trains = this.loadTrains() ?? [];
|
||||
setContextItem("trains", trains);
|
||||
|
||||
const resources = new ResourceManager();
|
||||
setContextItem("resources", resources);
|
||||
|
||||
const inputManager = new InputManager();
|
||||
setContextItem("inputManager", inputManager);
|
||||
|
||||
bootstrapInputs();
|
||||
|
||||
resources.set("engine-sprites", new Image());
|
||||
resources.get<HTMLImageElement>("engine-sprites")!.src =
|
||||
"/sprites/EngineSprites.png";
|
||||
resources.ready().then(() => {
|
||||
this.stateMachine.transitionTo(States.RUNNING);
|
||||
});
|
||||
|
||||
const doodler = getContextItem<Doodler>("doodler");
|
||||
this.layers.push(doodler.createLayer((_, __, dTime) => {
|
||||
doodler.clearRect(new Vector(0, 0), doodler.width, doodler.height);
|
||||
doodler.fillRect(new Vector(0, 0), doodler.width, doodler.height, {
|
||||
color: "#302040",
|
||||
});
|
||||
}));
|
||||
}
|
||||
override stop(): void {
|
||||
// noop
|
||||
}
|
||||
|
||||
private loadTrack() {
|
||||
const track = TrackSystem.deserialize(
|
||||
JSON.parse(localStorage.getItem("track") || "[]"),
|
||||
);
|
||||
return track ?? new TrackSystem([new StraightTrack()]);
|
||||
}
|
||||
|
||||
private loadTrains() {
|
||||
const trains = JSON.parse(localStorage.getItem("trains") || "[]");
|
||||
return trains;
|
||||
}
|
||||
}
|
30
src/state/states/PausedState.ts
Normal file
30
src/state/states/PausedState.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { State } from "../machine.ts";
|
||||
import { States } from "./index.ts";
|
||||
|
||||
export class PausedState extends State<States> {
|
||||
override name: States = States.PAUSED;
|
||||
override validTransitions: Set<States> = new Set([
|
||||
States.LOAD,
|
||||
States.RUNNING,
|
||||
States.EDIT_TRACK,
|
||||
States.EDIT_TRAIN,
|
||||
]);
|
||||
override update(dt: number): void {
|
||||
throw new Error("Method not implemented.");
|
||||
// TODO
|
||||
// Handle input
|
||||
// Draw ui
|
||||
}
|
||||
override start(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
// TODO
|
||||
// Save tracks to cache
|
||||
// Save trains to cache
|
||||
// Save resources to cache
|
||||
}
|
||||
override stop(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
// TODO
|
||||
// Do nothing
|
||||
}
|
||||
}
|
88
src/state/states/RunningState.ts
Normal file
88
src/state/states/RunningState.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { Doodler } from "@bearmetal/doodler";
|
||||
import { getContext, getContextItem } from "../../lib/context.ts";
|
||||
import { InputManager } from "../../lib/input.ts";
|
||||
import { TrackSystem } from "../../track/system.ts";
|
||||
import { Tender } from "../../train/cars.ts";
|
||||
import { RedEngine } from "../../train/engines.ts";
|
||||
import { DotFollower } from "../../train/newTrain.ts";
|
||||
import { Train } from "../../train/train.ts";
|
||||
import { State } from "../machine.ts";
|
||||
import { States } from "./index.ts";
|
||||
|
||||
export class RunningState extends State<States> {
|
||||
override name: States = States.RUNNING;
|
||||
override validTransitions: Set<States> = new Set([
|
||||
States.PAUSED,
|
||||
States.EDIT_TRACK,
|
||||
]);
|
||||
|
||||
layers: number[] = [];
|
||||
|
||||
override update(dt: number): void {
|
||||
const ctx = getContext() as { trains: Train[]; track: TrackSystem };
|
||||
// const ctx = getContext() as { trains: DotFollower[]; track: TrackSystem };
|
||||
// TODO
|
||||
// Update trains
|
||||
// Update world
|
||||
// Handle input
|
||||
// Monitor world events
|
||||
for (const train of ctx.trains) {
|
||||
train.move(dt);
|
||||
}
|
||||
}
|
||||
override start(): void {
|
||||
console.log("Starting running state");
|
||||
const doodler = getContextItem<Doodler>("doodler");
|
||||
this.layers.push(
|
||||
doodler.createLayer(() => {
|
||||
const track = getContextItem<TrackSystem>("track");
|
||||
track.draw();
|
||||
}),
|
||||
doodler.createLayer(() => {
|
||||
const trains = getContextItem<Train[]>("trains");
|
||||
for (const train of trains) {
|
||||
// if (input.getKeyState("ArrowUp")) {
|
||||
// train.acceleration.x += 10;
|
||||
// }
|
||||
train.draw();
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
// noop
|
||||
const inputManager = getContextItem<InputManager>("inputManager");
|
||||
const track = getContextItem<TrackSystem>("track");
|
||||
const ctx = getContext() as { trains: Train[] };
|
||||
// const ctx = getContext() as { trains: DotFollower[] };
|
||||
inputManager.onKey(" ", () => {
|
||||
// const path = track.path;
|
||||
// const follower = new DotFollower(path, path.points[0].copy());
|
||||
// ctx.trains.push(follower);
|
||||
const train = new Train(track.path, [new RedEngine(), new Tender()]);
|
||||
ctx.trains.push(train);
|
||||
});
|
||||
// const trainCount = 2000;
|
||||
// for (let i = 0; i < trainCount; i++) {
|
||||
// const train = new Train(track.path, [new RedEngine(), new Tender()]);
|
||||
// ctx.trains.push(train);
|
||||
// }
|
||||
|
||||
inputManager.onKey("ArrowUp", () => {
|
||||
const trains = getContextItem<Train[]>("trains");
|
||||
for (const train of trains) {
|
||||
train.speed += 1;
|
||||
}
|
||||
});
|
||||
inputManager.onKey("ArrowDown", () => {
|
||||
const trains = getContextItem<Train[]>("trains");
|
||||
for (const train of trains) {
|
||||
train.speed -= 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
override stop(): void {
|
||||
for (const layer of this.layers) {
|
||||
getContextItem<Doodler>("doodler").deleteLayer(layer);
|
||||
}
|
||||
}
|
||||
}
|
25
src/state/states/index.ts
Normal file
25
src/state/states/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { StateMachine } from "../machine.ts";
|
||||
import { EditTrainState } from "./EditTrainState.ts";
|
||||
import { EditTrackState } from "./EditTrackState.ts";
|
||||
import { PausedState } from "./PausedState.ts";
|
||||
import { RunningState } from "./RunningState.ts";
|
||||
import { LoadState } from "./LoadState.ts";
|
||||
|
||||
export enum States {
|
||||
LOAD,
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
EDIT_TRACK,
|
||||
EDIT_TRAIN,
|
||||
}
|
||||
|
||||
export function bootstrapGameStateMachine() {
|
||||
const stateMachine = new StateMachine<States>();
|
||||
stateMachine.addState(new LoadState(stateMachine));
|
||||
stateMachine.addState(new RunningState(stateMachine));
|
||||
stateMachine.addState(new PausedState(stateMachine));
|
||||
stateMachine.addState(new EditTrackState(stateMachine));
|
||||
stateMachine.addState(new EditTrainState(stateMachine));
|
||||
stateMachine.transitionTo(States.LOAD);
|
||||
return stateMachine;
|
||||
}
|
Reference in New Issue
Block a user