115 lines
2.6 KiB
TypeScript
115 lines
2.6 KiB
TypeScript
import { cls } 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);
|
|
|
|
if (level != undefined) {
|
|
draw_level(level, 0, 0);
|
|
}
|
|
|
|
for (const actor of actors) {
|
|
actor.draw(clock);
|
|
}
|
|
|
|
// log("FRAME TIME:", since_last_frame());
|
|
draw_log();
|
|
}
|