meat/app/assets.ts
2026-08-04 13:53:59 +02:00

57 lines
2 KiB
TypeScript

import type { Texture } from "../engine/render/Texture"
import barkUrl from "../assets/bark.png"
import crateUrl from "../assets/crate.png"
import floorUrl from "../assets/floor.png"
import grassUrl from "../assets/grass.png"
import leafUrl from "../assets/leaf.png"
import needleUrl from "../assets/needle.png"
import npcUrl from "../assets/npc.png"
import wallUrl from "../assets/wall.png"
export type Textures = {
floor: Texture
grass: Texture
bark: Texture
leaf: Texture
needle: Texture
wall: Texture
crate: Texture
npc: Texture
}
/** Load every game texture up front. Call once before starting the loop. */
export async function loadTextures(): Promise<Textures> {
const [floor, grass, bark, leaf, needle, wall, crate, npc] = await Promise.all([
loadTexture(floorUrl),
loadTexture(grassUrl),
loadTexture(barkUrl),
loadTexture(leafUrl),
loadTexture(needleUrl),
loadTexture(wallUrl),
loadTexture(crateUrl),
loadTexture(npcUrl),
])
return { floor, grass, bark, leaf, needle, wall, crate, npc }
}
function loadTexture(url: string): Promise<Texture> {
return new Promise((resolve, reject) => {
const image = new Image()
image.addEventListener("load", () => resolve(toTexture(image)))
image.addEventListener("error", () => reject(new Error(`failed to load ${url}`)))
image.src = url
})
}
/** Draw a loaded image into a canvas and read its pixels back as a Texture.
* ImageData bytes are RGBA, identical to how Color packs a Uint32, so the
* buffer is reused directly with no per-pixel conversion. */
function toTexture(image: HTMLImageElement): Texture {
const canvas = document.createElement("canvas")
canvas.width = image.naturalWidth
canvas.height = image.naturalHeight
const ctx = canvas.getContext("2d")!
ctx.drawImage(image, 0, 0)
const pixels = ctx.getImageData(0, 0, canvas.width, canvas.height)
return { width: pixels.width, height: pixels.height, data: new Uint32Array(pixels.data.buffer) }
}