import { cls, get_dimensions, scale } from "./graphics"; import { since_start } from "./time"; import { new_v2 } from "./vector"; import { load_world, World, Level, 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 level: Level | 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 level = world.levels.find((l) => l.world_x == 0 && l.world_y == 0); if (!level) { throw new Error("UNABLE TO FIND LEVEL AT 0,0: CANNOT START"); } // 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! ", 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! ", actors.length, "actors"); } } export function update() { if (!level) { return; } clock = (clock + 1) % 20160; for (const actor of actors) { actor.update(); } for (const actor of actors) { actor.update_physics(level); } // 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 (level != undefined) { draw_level(level, 0, 0); } for (const actor of actors) { actor.draw(clock); } // log("FRAME TIME:", since_last_frame()); draw_log(); }