Now we return Texture objects to make things a little bit more type-safe, at the cost of a small allocation (I hope!)
119 lines
2.5 KiB
TypeScript
119 lines
2.5 KiB
TypeScript
import { cls, print, spr, use_texture, Texture } from "./graphics";
|
|
import { load_texture } from "./assets";
|
|
import { since_start } from "./time";
|
|
import { btn, Button } from "./input";
|
|
// import { load_string } from "./io";
|
|
import { new_v2, vadd, vmul, vnorm } from "./vector";
|
|
|
|
/// TODO: Support reload by saving and restoring state from init/update/restore.
|
|
|
|
/// A nice looping frame counter.
|
|
let clock = 0;
|
|
|
|
let bot_sprite: Texture | undefined = undefined;
|
|
|
|
// Note zelda overworld is 16x8 screens
|
|
// zelda screen is 16x11 tiles
|
|
// from a feeling point of view this is sufficient, apparently :D
|
|
|
|
let loaded = false;
|
|
|
|
async function load_map(path: string) {
|
|
// print("Loading map:", path);
|
|
// const blob = await load_string(path);
|
|
// const map = JSON.parse(blob);
|
|
// print("Loaded map:", map);
|
|
}
|
|
|
|
function load_assets() {
|
|
// Start this load, but then...
|
|
let texture_load = load_texture("./bot.png").then((n) => {
|
|
print("Bot loaded at", since_start());
|
|
bot_sprite = n;
|
|
});
|
|
|
|
let map_load = load_map("./overworld.ldtk");
|
|
|
|
Promise.all([texture_load, map_load]).then(() => {
|
|
loaded = true;
|
|
print("All are loaded.");
|
|
});
|
|
}
|
|
|
|
export function init() {
|
|
print("Hello world!");
|
|
load_assets();
|
|
}
|
|
|
|
const friction = 0.6;
|
|
let robo_vel = new_v2(0);
|
|
let robo_pos = new_v2(10);
|
|
|
|
export function update() {
|
|
clock = (clock + 1) % 20160;
|
|
|
|
// Acceleration from input
|
|
let a = new_v2(0);
|
|
if (btn(Button.Up)) {
|
|
a.y -= 1;
|
|
}
|
|
if (btn(Button.Down)) {
|
|
a.y += 1;
|
|
}
|
|
if (btn(Button.Left)) {
|
|
a.x -= 1;
|
|
}
|
|
if (btn(Button.Right)) {
|
|
a.x += 1;
|
|
}
|
|
vnorm(a);
|
|
a = vmul(a, 0.8); // Speed.
|
|
|
|
// Friction
|
|
let v = vmul(robo_vel, friction);
|
|
v = vadd(v, a);
|
|
|
|
// Zero if we're smaller than some epsilon.
|
|
if (Math.abs(v.x) < 0.01) {
|
|
v.x = 0;
|
|
}
|
|
if (Math.abs(v.y) < 0.01) {
|
|
v.y = 0;
|
|
}
|
|
|
|
// Motion
|
|
let np = vadd(robo_pos, v);
|
|
|
|
// TODO: Collide.
|
|
|
|
robo_pos = np;
|
|
robo_vel = v;
|
|
}
|
|
|
|
// GARBAGE OBVIOUSLY
|
|
const robo_info = {
|
|
width: 32,
|
|
height: 32,
|
|
animations: [
|
|
{ start: 0, length: 1, speed: 20 },
|
|
{ start: 1, length: 4, speed: 8 },
|
|
],
|
|
};
|
|
|
|
export function draw() {
|
|
cls(0.1, 0.2, 0.3);
|
|
if (!loaded) {
|
|
return;
|
|
}
|
|
|
|
if (bot_sprite != undefined) {
|
|
// ...it gets resolved here?
|
|
use_texture(bot_sprite);
|
|
|
|
const moving = robo_vel.x != 0 || robo_vel.y != 0;
|
|
const anim = robo_info.animations[moving ? 1 : 0];
|
|
const frame = (anim.start + ((clock / anim.speed) % anim.length)) >> 0;
|
|
spr(robo_pos.x, robo_pos.y, 32, 32, frame * robo_info.width, 0, 32, 32);
|
|
}
|
|
// print("FRAME TIME:", since_last_frame());
|
|
}
|