oden/game/main.ts
John Doty 93d4e3eb91 [oden][game] Multiple screens, logging, pre/post, bluescreen
Better blue screens and also logging and whatnot
2023-09-11 20:41:11 -07:00

114 lines
2.5 KiB
TypeScript

import { cls, get_dimensions, scale } from "./graphics";
import { since_start } from "./time";
import { new_v2 } from "./vector";
import { load_world, World, draw_level } from "./level";
import {
Actor,
ActorProps,
ActorType,
new_actor_props,
is_actor_type,
spawn_actor,
} from "./actor";
import { log, draw_log } from "./log";
/// A nice looping frame counter.
let clock = 0;
let world: World | undefined = undefined;
let actors: Actor[] = [];
// Note zelda overworld is 16x8 screens
// zelda screen is 16x11 tiles
// from a feeling point of view this is sufficient, apparently :D
function start_load_assets() {
// Start this load, but then...
load_world("./overworld.ldtk").then((w) => {
log("world loaded at", since_start());
world = w;
// Assume we start at 0,0
const level = world.current_level;
// TODO: SPAWN ACTORS BASED ON LEVEL.
actors.length = 0;
for (const entity of level.entities) {
if (is_actor_type(entity.type)) {
const [x, y] = entity.px;
const [w, _] = entity.bounds;
const props = new_actor_props(entity.id, new_v2(x, y), w);
actors.push(spawn_actor(entity.type, props));
} else {
log("WARNING: Ignoring entity of type", entity.type);
}
}
});
}
// TODO: Build a system whereby the signatures of the fundamental functions can be checked.
export function init() {
log("Hello world!");
start_load_assets();
}
interface Snapshot {
clock: number;
actors: { type: ActorType; props: ActorProps }[];
}
export function suspend(): Snapshot {
log("suspend_status", "Suspend ", actors.length, "actors");
return {
clock,
actors: actors.map((a) => {
return { type: a.type, props: a.props };
}),
};
}
export function resume(snapshot: Snapshot | undefined) {
if (snapshot) {
clock = snapshot.clock || 0;
actors = snapshot.actors.map((s) => spawn_actor(s.type, s.props));
log("resume_status", "Resume ", actors.length, "actors");
}
}
export function update() {
if (!world) {
return;
}
clock = (clock + 1) % 20160;
for (const actor of actors) {
actor.update(world);
}
// TODO: Bonks
// TODO: Transients
}
export function draw() {
cls(0.1, 0.2, 0.3);
const dimensions = get_dimensions();
const s = Math.max(
1,
Math.floor(Math.min(dimensions[0] / 320, dimensions[1] / 240))
);
scale(s);
if (world != undefined) {
draw_level(world.current_level, 0, 0);
}
for (const actor of actors) {
actor.draw(clock);
}
// log("FRAME TIME:", since_last_frame());
draw_log();
}