37 lines
1.2 KiB
TypeScript
37 lines
1.2 KiB
TypeScript
import type { Palette } from "../world/types";
|
|
|
|
/** Decode Game Boy planar pixels directly to RGBA; no display hardware emulation. */
|
|
export function drawTile(
|
|
target: Uint8ClampedArray,
|
|
width: number,
|
|
height: number,
|
|
graphics: Uint8Array,
|
|
tile: number,
|
|
x: number,
|
|
y: number,
|
|
palette: Palette,
|
|
options: { transparent?: boolean; flipX?: boolean; flipY?: boolean } = {},
|
|
) {
|
|
const offset = tile * 16;
|
|
if (offset < 0 || offset + 16 > graphics.length) return;
|
|
for (let row = 0; row < 8; row++) {
|
|
const sourceRow = options.flipY ? 7 - row : row;
|
|
const lo = graphics[offset + sourceRow * 2],
|
|
hi = graphics[offset + sourceRow * 2 + 1];
|
|
for (let col = 0; col < 8; col++) {
|
|
const bit = options.flipX ? col : 7 - col;
|
|
const index = ((lo >> bit) & 1) | (((hi >> bit) & 1) << 1);
|
|
if (options.transparent && index === 0) continue;
|
|
const px = x + col,
|
|
py = y + row;
|
|
if (px < 0 || py < 0 || px >= width || py >= height) continue;
|
|
const destination = (py * width + px) * 4,
|
|
color = palette[index];
|
|
target[destination] = color[0];
|
|
target[destination + 1] = color[1];
|
|
target[destination + 2] = color[2];
|
|
target[destination + 3] = 255;
|
|
}
|
|
}
|
|
}
|