From ec41f332f2f843ebb33e7106a1daa3f076e27e6e Mon Sep 17 00:00:00 2001 From: Schluffe Date: Fri, 20 Feb 2026 10:48:19 +0100 Subject: [PATCH] Well it works again --- engine/Scene.ts | 1 - engine/{sprites.ts => Sprite.ts} | 40 +++++++++++++++++++++++------- game/entities/hero/entity.ts | 7 +++--- game/entities/portal/entity.ts | 5 ++-- game/entities/testEntity/entity.ts | 9 +++---- game/scenes/testScene/scene.ts | 6 +++-- 6 files changed, 44 insertions(+), 24 deletions(-) rename engine/{sprites.ts => Sprite.ts} (57%) diff --git a/engine/Scene.ts b/engine/Scene.ts index b136bbe..83ad7b1 100644 --- a/engine/Scene.ts +++ b/engine/Scene.ts @@ -1,5 +1,4 @@ import { - type Entity, entityMap, entityProcessMap, type Process as ProcessEntity, diff --git a/engine/sprites.ts b/engine/Sprite.ts similarity index 57% rename from engine/sprites.ts rename to engine/Sprite.ts index e893202..a69f315 100644 --- a/engine/sprites.ts +++ b/engine/Sprite.ts @@ -1,4 +1,6 @@ -export type SpritesSheet = { +import { loadImage } from "./lib/loadImage"; + +export type SpriteSheet = { image: HTMLImageElement; xFrames: number; yFrames: number; @@ -7,18 +9,23 @@ export type SpritesSheet = { }; export type SpriteAnimation = { - sheet: SpritesSheet; + src: string; xIndex: number; yIndex: number; frameTime: number; frameDelta: number; }; -export function createSpritesSheet( +// It's not possible to crate a structured clone of a HTMLImageElement and it would be a +// waste of memory anyways since we use the HTMLImageElement only as reference for draw calls. +// Therefore the SpriteSheet will stored by it's image source. +export const spriteSheetMap = new Map(); + +export function createSpriteSheet( image: HTMLImageElement, xFrames: number, yFrames: number, -): SpritesSheet { +): SpriteSheet { return { image, xFrames, @@ -28,13 +35,26 @@ export function createSpritesSheet( }; } +export async function useSpriteSheetSrc( + src: string, + xFrames: number, + yFrames: number, +): Promise { + spriteSheetMap.set( + src, + createSpriteSheet(await loadImage(src), xFrames, yFrames), + ); + + return src; +} + export function createSpriteAnimation( - sheet: SpritesSheet, + src: string, frameTime: number, yIndex: number, ): SpriteAnimation { return { - sheet, + src, xIndex: 0, yIndex, frameTime, @@ -44,7 +64,7 @@ export function createSpriteAnimation( export function drawSprite( ctx: CanvasRenderingContext2D, - sheet: SpritesSheet, + sheet: SpriteSheet, xIndex: number, yIndex: number, x: number, @@ -72,12 +92,14 @@ export function playAnimation( y: number, delta: number, ): void { + const sheet = spriteSheetMap.get(animation.src)!; + if ((animation.frameDelta += delta) > animation.frameTime) { animation.frameDelta = 0; - if ((animation.xIndex += 1) >= animation.sheet.xFrames) { + if ((animation.xIndex += 1) >= sheet.xFrames) { animation.xIndex = 0; } } - drawSprite(ctx, animation.sheet, animation.xIndex, animation.yIndex, x, y); + drawSprite(ctx, sheet, animation.xIndex, animation.yIndex, x, y); } diff --git a/game/entities/hero/entity.ts b/game/entities/hero/entity.ts index 6ffe656..645a1e7 100644 --- a/game/entities/hero/entity.ts +++ b/game/entities/hero/entity.ts @@ -2,13 +2,12 @@ import { type Circle, createCircle } from "#/engine/Circle.ts"; import { moveAndCollide } from "#/engine/Collision.ts"; import { defineEntity } from "#/engine/Entity.ts"; import { keyboardInput } from "#/engine/Keyboard.ts"; -import { loadImage } from "#/engine/lib/loadImage"; import { pointer } from "#/engine/Pointer.ts"; import { createSpriteAnimation, - createSpritesSheet, type SpriteAnimation, -} from "#/engine/sprites.ts"; + useSpriteSheetSrc, +} from "#/engine/Sprite.ts"; import { createVector, type Vector } from "#/engine/Vector.ts"; import charIdle from "#/game/assets/char-idle.png"; @@ -20,7 +19,7 @@ export type Hero = { }; const speed = 0.05; -const idleSheet = createSpritesSheet(await loadImage(charIdle), 2, 4); +const idleSheet = await useSpriteSheetSrc(charIdle, 2, 4); const state: Hero = { position: createVector(), diff --git a/game/entities/portal/entity.ts b/game/entities/portal/entity.ts index 457e548..06217d5 100644 --- a/game/entities/portal/entity.ts +++ b/game/entities/portal/entity.ts @@ -1,9 +1,8 @@ import { defineEntity } from "#/engine/Entity.ts"; -import { loadImage } from "#/engine/lib/loadImage.ts"; -import { createSpriteAnimation, createSpritesSheet } from "#/engine/sprites.ts"; +import { createSpriteAnimation, useSpriteSheetSrc } from "#/engine/Sprite.ts"; import portal from "#/game/assets/portal.png"; -const portalSheet = createSpritesSheet(await loadImage(portal), 3, 1); +const portalSheet = await useSpriteSheetSrc(portal, 3, 1); defineEntity("portal", { animation: createSpriteAnimation(portalSheet, 400, 0), diff --git a/game/entities/testEntity/entity.ts b/game/entities/testEntity/entity.ts index 632b259..990de7c 100644 --- a/game/entities/testEntity/entity.ts +++ b/game/entities/testEntity/entity.ts @@ -1,18 +1,17 @@ import { defineEntity } from "#/engine/Entity.ts"; -import { loadImage } from "#/engine/lib/loadImage.ts"; import { createSpriteAnimation, - createSpritesSheet, type SpriteAnimation, -} from "#/engine/sprites.ts"; + useSpriteSheetSrc, +} from "#/engine/Sprite.ts"; import { createVector, type Vector } from "#/engine/Vector.ts"; import { viewport } from "#/engine/Viewport.ts"; import charIdle from "#/game/assets/char-idle.png"; import charWalk from "#/game/assets/char-walk.png"; const sprites = { - idle: createSpritesSheet(await loadImage(charIdle), 2, 4), - walk: createSpritesSheet(await loadImage(charWalk), 4, 4), + idle: await useSpriteSheetSrc(charIdle, 2, 4), + walk: await useSpriteSheetSrc(charWalk, 4, 4), }; const animations = { diff --git a/game/scenes/testScene/scene.ts b/game/scenes/testScene/scene.ts index d58e682..56d529d 100644 --- a/game/scenes/testScene/scene.ts +++ b/game/scenes/testScene/scene.ts @@ -1,6 +1,7 @@ import { strokeCircle } from "#/engine/Circle.ts"; import { pointer } from "#/engine/Pointer.ts"; import { defineScene } from "#/engine/Scene.ts"; +import { spriteSheetMap } from "#/engine/Sprite.ts"; import type { Hero } from "#/game/entities/hero/entity.ts"; import data from "./data.json"; @@ -11,9 +12,10 @@ linkScenes(["fooScene"] as const); preProcess((entityInstanceMap) => { const entry = entityInstanceMap.get("hero")!; const instance = entry.instances[0] as Hero; + const sheet = spriteSheetMap.get(instance.animation.src)!; - instance.position.x = data.width - instance.animation.sheet.frameHeight; - instance.position.y = data.height - instance.animation.sheet.frameWidth; + instance.position.x = data.width - sheet.frameHeight; + instance.position.y = data.height - sheet.frameWidth; }); process((ctx, _delta) => {