Skip to content
This repository was archived by the owner on Aug 16, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/image-data/bitmap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { palette } from '../base/index.js'

const uInt8Cache: Map<string, Uint8ClampedArray> = new Map();

// At odds with in-game behavior... doesn't enforce a size with stretching.
export const bitmapTextToImageData = (key: string, text: string): ImageData => {
const rows = text.trim().split("\n").map(x => x.trim())
Expand All @@ -8,7 +10,14 @@ export const bitmapTextToImageData = (key: string, text: string): ImageData => {
if (!isRect) throw new Error(`Bitmap with key ${key} is not rectangular.`);
const width = rows[0]!.length || 1
const height = rows.length || 1
const data = new Uint8ClampedArray(width*height*4)

// If possible, use a cached Uint8ClampedArray
const cacheKey = width + ',' + height;
const data = uInt8Cache.get(cacheKey) ?? new Uint8ClampedArray(width*height*4)
data.fill(0)

// Add the Uint8ClampedArray to the cache if it doesn't already exist
if (!uInt8Cache.has(cacheKey)) uInt8Cache.set(cacheKey, data);

const colors = Object.fromEntries(palette)

Expand All @@ -30,4 +39,4 @@ export const bitmapTextToImageData = (key: string, text: string): ImageData => {
}

return new ImageData(data, width, height)
}
}
20 changes: 20 additions & 0 deletions src/web/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ export type WebEngineAPI = BaseEngineAPI & Pick<
getState(): GameState // For weird backwards-compatibility reasons, not part of API
}

const SPRITE_CACHE_SIZE = 64;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value was chosen after determining that 16 and 32 didn't have a noticable impact.

const spriteCache: Map<string, CanvasImageSource> = new Map();

function updateSpriteCache(key: string, value: CanvasImageSource) {
spriteCache.set(key, value);
if (spriteCache.size > SPRITE_CACHE_SIZE) {
spriteCache.delete(spriteCache.keys().next().value);
}
}

export function webEngine(canvas: HTMLCanvasElement): {
api: WebEngineAPI,
state: GameState,
Expand Down Expand Up @@ -106,10 +116,20 @@ export function webEngine(canvas: HTMLCanvasElement): {

for (let i = 0; i < bitmaps.length; i++) {
const [ key, value ] = bitmaps[i]!

// If possible, use a cached sprite canvas object
if (spriteCache.has(value)) {
const littleCanvas = spriteCache.get(value)!;
_bitmaps[key] = littleCanvas;
continue;
}

const imgData = bitmapTextToImageData(key, value)
const littleCanvas = makeCanvas(16, 16)
littleCanvas.getContext('2d')!.putImageData(imgData, 0, 0)
_bitmaps[key] = littleCanvas

updateSpriteCache(value, littleCanvas);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/web/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import type { TextElement } from '../api.js'
import { font, composeText } from '../base/index.js'
import { makeCanvas } from './util.js'

const img = new ImageData(160, 128)

export const getTextImg = (texts: TextElement[]): CanvasImageSource => {
const charGrid = composeText(texts)
const img = new ImageData(160, 128)
img.data.fill(0)

for (const [i, row] of Object.entries(charGrid)) {
Expand Down Expand Up @@ -32,4 +33,4 @@ export const getTextImg = (texts: TextElement[]): CanvasImageSource => {
canvas.getContext('2d')!.putImageData(img, 0, 0)

return canvas
}
}