feat: bootstrap walking skeleton
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import type { Content } from '../content/schema';
|
||||
|
||||
/**
|
||||
* Core game state and per-tick simulation.
|
||||
*
|
||||
* Pure TS — no React, no DOM, no wall clock. The tick loop (tickLoop.ts) drives
|
||||
* `tickGame` once per tick; `now`/scheduling lives entirely outside this module.
|
||||
*/
|
||||
|
||||
export interface GameState {
|
||||
/** resourceId -> current amount. */
|
||||
resources: Record<string, number>;
|
||||
/** The action currently running, or null. */
|
||||
activeActionId: string | null;
|
||||
/** Progress of the active action, in milliseconds. */
|
||||
actionElapsedMs: number;
|
||||
}
|
||||
|
||||
export function createGameState(content: Content): GameState {
|
||||
const resources: Record<string, number> = {};
|
||||
for (const resource of content.resources) {
|
||||
resources[resource.id] = resource.startAmount;
|
||||
}
|
||||
return { resources, activeActionId: null, actionElapsedMs: 0 };
|
||||
}
|
||||
|
||||
/** Begin running an action, resetting its progress. Throws on an unknown id. */
|
||||
export function startAction(state: GameState, content: Content, actionId: string): void {
|
||||
if (!content.actionsById[actionId]) {
|
||||
throw new Error(`Unknown action "${actionId}"`);
|
||||
}
|
||||
state.activeActionId = actionId;
|
||||
state.actionElapsedMs = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance the active action by `tickMs`. Each time it reaches its duration it
|
||||
* grants its yield and repeats, carrying the remainder — so one large tick (the
|
||||
* offline catch-up path) can complete an action many times.
|
||||
*/
|
||||
export function tickGame(state: GameState, content: Content, tickMs: number): void {
|
||||
if (!state.activeActionId) {
|
||||
return;
|
||||
}
|
||||
const action = content.actionsById[state.activeActionId];
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.actionElapsedMs += tickMs;
|
||||
while (state.actionElapsedMs >= action.durationMs) {
|
||||
state.actionElapsedMs -= action.durationMs;
|
||||
state.resources[action.yields.resourceId] += action.yields.amount;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user