Separates game loop from doodler draw loop. Each state is in charge of registering and unregistering layers
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
import { getContext } from "../lib/context.ts";
|
||||
import { TrackSystem } from "../track/system.ts";
|
||||
import { Train } from "../train.old.ts";
|
||||
|
||||
export class StateMachine<T> {
|
||||
private _states: Map<T, State<T>> = new Map();
|
||||
private currentState?: State<T>;
|
||||
@@ -6,6 +10,13 @@ export class StateMachine<T> {
|
||||
this.currentState?.update(dt, ctx);
|
||||
}
|
||||
|
||||
optimizePerformance(percent: number) {
|
||||
const ctx = getContext() as { trains: Train[]; track: TrackSystem };
|
||||
if (percent < 0.5) {
|
||||
ctx.track.optimize(percent);
|
||||
}
|
||||
}
|
||||
|
||||
get current() {
|
||||
return this.currentState;
|
||||
}
|
||||
|
@@ -33,6 +33,8 @@ export class EditTrackState extends State<States> {
|
||||
private ghostRotated = false;
|
||||
private closestEnd?: End;
|
||||
|
||||
layers: number[] = [];
|
||||
|
||||
override update(dt: number): void {
|
||||
const inputManager = getContextItem<InputManager>("inputManager");
|
||||
const track = getContextItem<TrackSystem>("track");
|
||||
@@ -138,22 +140,6 @@ export class EditTrackState extends State<States> {
|
||||
this.ghostSegment = undefined;
|
||||
this.ghostRotated = false;
|
||||
}
|
||||
|
||||
this.selectedSegment?.draw();
|
||||
if (this.ghostSegment) {
|
||||
doodler.drawWithAlpha(0.5, () => {
|
||||
if (!this.ghostSegment) return;
|
||||
this.ghostSegment.draw();
|
||||
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] });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// manipulate only end of segment while maintaining length
|
||||
@@ -263,13 +249,34 @@ export class EditTrackState extends State<States> {
|
||||
track.translate(translation);
|
||||
}
|
||||
|
||||
track.draw(true);
|
||||
// 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();
|
||||
if (this.ghostSegment) {
|
||||
doodler.drawWithAlpha(0.5, () => {
|
||||
if (!this.ghostSegment) return;
|
||||
this.ghostSegment.draw();
|
||||
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(),
|
||||
@@ -376,9 +383,19 @@ export class EditTrackState extends State<States> {
|
||||
|
||||
// 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 inputManager = getContextItem<InputManager>("inputManager");
|
||||
inputManager.offKey("e");
|
||||
inputManager.offKey("w");
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { Doodler, Vector } from "@bearmetal/doodler";
|
||||
import { bootstrapInputs } from "../../inputs.ts";
|
||||
import { setContextItem } from "../../lib/context.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";
|
||||
@@ -13,6 +14,8 @@ export class LoadState extends State<States> {
|
||||
States.RUNNING,
|
||||
]);
|
||||
|
||||
layers: number[] = [];
|
||||
|
||||
override update(): void {
|
||||
// noop
|
||||
}
|
||||
@@ -37,6 +40,14 @@ export class LoadState extends State<States> {
|
||||
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
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { Doodler } from "@bearmetal/doodler";
|
||||
import { getContext, getContextItem } from "../../lib/context.ts";
|
||||
import { InputManager } from "../../lib/input.ts";
|
||||
import { TrackSystem } from "../../track/system.ts";
|
||||
@@ -14,26 +15,40 @@ export class RunningState extends State<States> {
|
||||
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 };
|
||||
const input = getContextItem<InputManager>("inputManager");
|
||||
// TODO
|
||||
// Update trains
|
||||
// Update world
|
||||
// Handle input
|
||||
// Draw (maybe via a layer system that syncs with doodler)
|
||||
ctx.track.draw();
|
||||
for (const train of ctx.trains) {
|
||||
// if (input.getKeyState("ArrowUp")) {
|
||||
// train.acceleration.x += 10;
|
||||
// }
|
||||
train.move(dt);
|
||||
train.draw();
|
||||
}
|
||||
// Monitor world events
|
||||
for (const train of ctx.trains) {
|
||||
train.move(dt);
|
||||
}
|
||||
}
|
||||
override start(): void {
|
||||
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");
|
||||
@@ -46,7 +61,7 @@ export class RunningState extends State<States> {
|
||||
const train = new Train(track.path, [new RedEngine(), new Tender()]);
|
||||
ctx.trains.push(train);
|
||||
});
|
||||
// const trainCount = 1000;
|
||||
// const trainCount = 2000;
|
||||
// for (let i = 0; i < trainCount; i++) {
|
||||
// const train = new Train(track.path, [new RedEngine(), new Tender()]);
|
||||
// ctx.trains.push(train);
|
||||
@@ -66,6 +81,8 @@ export class RunningState extends State<States> {
|
||||
});
|
||||
}
|
||||
override stop(): void {
|
||||
// noop
|
||||
for (const layer of this.layers) {
|
||||
getContextItem<Doodler>("doodler").deleteLayer(layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user