diff --git a/src/common/display/brick.tsx b/src/common/display/brick.tsx index ecb51d4..7413856 100644 --- a/src/common/display/brick.tsx +++ b/src/common/display/brick.tsx @@ -1,6 +1,6 @@ import { render } from "preact"; import type { Display } from "."; -import { clamp, ensureImageLoaded, range } from "@common/utils"; +import { clamp, range } from "@common/utils"; import classNames from "classnames"; import styles from './assets/brick.module.css'; @@ -12,7 +12,7 @@ const FIELD_HEIGHT = 20; const MINI_FIELD_WIDTH = 4; const MINI_FIELD_HEIGHT = 4; -interface BrickDisplayImage { +export interface BrickDisplayImage { image: boolean[]; width: number; height: number; @@ -241,20 +241,18 @@ export class BrickDisplay implements Display { height: 0, } - ensureImageLoaded(image).then(() => { - const canvas = document.createElement('canvas'); - result.width = canvas.width = image.naturalWidth; - result.height = canvas.height = image.naturalHeight; - const ctx = canvas.getContext('2d'); - if (ctx) { - ctx.drawImage(image, 0, 0); - const pxData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const canvas = document.createElement('canvas'); + result.width = canvas.width = image.naturalWidth; + result.height = canvas.height = image.naturalHeight; + const ctx = canvas.getContext('2d'); + if (ctx) { + ctx.drawImage(image, 0, 0); + const pxData = ctx.getImageData(0, 0, canvas.width, canvas.height); - for (let i = 0; i < pxData.data.length; i += 4) { - result.image[i >> 2] = pxData.data[i] < 128; - } + for (let i = 0; i < pxData.data.length; i += 4) { + result.image[i >> 2] = pxData.data[i] < 128; } - }); + } return result; } diff --git a/src/common/display/index.ts b/src/common/display/index.ts index ff14f98..714f5eb 100644 --- a/src/common/display/index.ts +++ b/src/common/display/index.ts @@ -3,4 +3,4 @@ export interface Display { update(): void; } -export { BrickDisplay } from './brick'; \ No newline at end of file +export { BrickDisplay, type BrickDisplayImage } from './brick'; \ No newline at end of file diff --git a/src/common/utils.ts b/src/common/utils.ts index da75e43..6c0bcca 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -21,9 +21,4 @@ export const intHash = (seed: number, ...parts: number[]) => { h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909); return h1; }; -export const sinHash = (...data: number[]) => data.reduce((hash, n) => Math.sin((hash * 123.12 + n) * 756.12), 0) / 2 + 0.5; - -export const ensureImageLoaded = async (image: HTMLImageElement): Promise => - image.naturalWidth === 0 - ? new Promise(r => image.addEventListener('load', () => r())) - : void 0; +export const sinHash = (...data: number[]) => data.reduce((hash, n) => Math.sin((hash * 123.12 + n) * 756.12), 0) / 2 + 0.5; \ No newline at end of file diff --git a/src/games/brick-dungeon/assets/icon.png b/src/games/brick-dungeon/assets/icon.png deleted file mode 100644 index c3ddb99..0000000 Binary files a/src/games/brick-dungeon/assets/icon.png and /dev/null differ diff --git a/src/games/brick-dungeon/assets/spritesheet.png b/src/games/brick-dungeon/assets/spritesheet.png index 1e693d5..5426caa 100644 Binary files a/src/games/brick-dungeon/assets/spritesheet.png and b/src/games/brick-dungeon/assets/spritesheet.png differ diff --git a/src/games/brick-dungeon/index.ts b/src/games/brick-dungeon/index.ts index 83c663b..bdd7d1a 100644 --- a/src/games/brick-dungeon/index.ts +++ b/src/games/brick-dungeon/index.ts @@ -1,15 +1,19 @@ -import { BrickDisplay } from "@common/display"; -import { delay, randBool, randInt } from "@common/utils"; +import { BrickDisplay, type BrickDisplayImage } from "@common/display"; +import { delay } from "@common/utils"; +import { isPressed, updateKeys } from "@common/input"; -import iconImage from './assets/icon.png'; -import background from './assets/background.png'; +import backgroundImage from './assets/background.png'; +import spritesheetImage from './assets/spritesheet.png'; let display: BrickDisplay; - -const iconSprite = BrickDisplay.convertImage(iconImage); -const backgroundSprite = BrickDisplay.convertImage(background); +let background: BrickDisplayImage; +let player: BrickDisplayImage; +const weapons: BrickDisplayImage[] = []; +const monsters: BrickDisplayImage[] = []; let bgY = 0; +let weapon = 0; +let monster = 0; function moveBackground() { bgY++; @@ -18,19 +22,43 @@ function moveBackground() { } } +let frames = 0; let prevFrameTime: number = 0; async function loop(time: number) { + frames++; const dt = time - prevFrameTime; prevFrameTime = time; - moveBackground(); + if (frames > 10) { + moveBackground(); + frames = 0; + } display.clear(); - display.drawImage(backgroundSprite, 0, bgY); - display.drawImage(backgroundSprite, 0, bgY + display.height); + display.clear(true); + + display.drawImage(background, 0, bgY); + display.drawImage(background, 0, bgY + display.height); + + display.drawImage(player, 3, 14); + display.drawImage(monsters[monster], 3, 2); + + display.drawImage(weapons[weapon], 0, 0, true); display.update(); - await delay(100); + + if (isPressed('arrowleft')) { + weapon = (weapon + weapons.length - 1) % weapons.length; + } else if (isPressed('arrowright')) { + weapon = (weapon + 1) % weapons.length; + } + if (isPressed('arrowup')) { + monster = (monster + monsters.length - 1) % monsters.length; + } else if (isPressed('arrowdown')) { + monster = (monster + 1) % monsters.length; + } + + updateKeys(); requestAnimationFrame(loop); } @@ -38,5 +66,19 @@ export default function main() { display = new BrickDisplay(); display.init(); + background = BrickDisplay.convertImage(backgroundImage); + const spritesheet = BrickDisplay.convertImage(spritesheetImage); + + for (let i = 0; i < 4; i++) { + weapons.push(BrickDisplay.extractSprite(spritesheet, i * 4, 0, 4, 4)); + } + for (let i = 0; i < 6; i++) { + monsters.push(BrickDisplay.extractSprite(spritesheet, i * 4, 12, 4, 4)); + } + for (let i = 0; i < 3; i++) { + monsters.push(BrickDisplay.extractSprite(spritesheet, i * 4, 16, 4, 4)); + } + player = BrickDisplay.extractSprite(spritesheet, 0, 8, 4, 4) + requestAnimationFrame(loop); } \ No newline at end of file