From 310355104a1cdbd3e82eebc5cbb7c42819991929 Mon Sep 17 00:00:00 2001 From: Andre Padez Date: Sun, 19 Oct 2025 02:30:50 +0100 Subject: [PATCH] useHeroRender --- src/useGame.ts | 8 +-- src/useHero/index.ts | 1 + src/useHero/useHeroRender.ts | 74 ++++++++++++++++++++++++++++ src/useKeyBindings/useKeyBindings.ts | 4 +- 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 src/useHero/index.ts create mode 100644 src/useHero/useHeroRender.ts diff --git a/src/useGame.ts b/src/useGame.ts index 3d590a3..0a9f3d8 100644 --- a/src/useGame.ts +++ b/src/useGame.ts @@ -1,18 +1,20 @@ import type { GameManager, GameOptions } from './types'; import { useBoard } from './useBoard'; import { useCursor } from './useCursor'; +import { useHeroRender } from './useHero'; import { useKeyBindings } from './useKeyBindings'; import { useGameStatus } from './useGameStatus'; export function useGame(options: GameOptions, platformHook?: unknown): GameManager { const { cols, rows } = options; - const boardManager = useBoard(cols, rows); - const { containerRef, renderBoard } = boardManager; - const cursor = useCursor(boardManager); + const board = useBoard(cols, rows); + const { containerRef, renderBoard } = board; + const cursor = useCursor(board); const gameStatusManager = useGameStatus(); const { gameStatus, startGame, togglePause, quitGame } = gameStatusManager; + useHeroRender({ gameStatus, board, cursor }); const keyManager = useKeyBindings({ cursor, gameStatus }); const gameManager = { diff --git a/src/useHero/index.ts b/src/useHero/index.ts new file mode 100644 index 0000000..19743ad --- /dev/null +++ b/src/useHero/index.ts @@ -0,0 +1 @@ +export * from './useHeroRender'; diff --git a/src/useHero/useHeroRender.ts b/src/useHero/useHeroRender.ts new file mode 100644 index 0000000..75a26c3 --- /dev/null +++ b/src/useHero/useHeroRender.ts @@ -0,0 +1,74 @@ +import { useEffect } from "react"; +import type { BoardManager, Cursor, GameStatus } from "../types"; + +type UseHeroRenderParams = { + gameStatus: GameStatus; + board: BoardManager; + cursor: Cursor; + relative?: boolean; +}; + +export function useHeroRender(params: UseHeroRenderParams) { + const { gameStatus, board, cursor, relative = true } = params; + const { containerRef } = board; + const playerPos = cursor.position(); + + const applyRelativeNumbers = (mazeDiv: HTMLElement, R: number, C: number) => { + const rows = Number(mazeDiv.dataset.rows || 0); + const cols = Number(mazeDiv.dataset.cols || 0); + + const rowNums = mazeDiv.querySelectorAll(".number.row[data-r]"); + rowNums.forEach((el) => { + const r = Number(el.getAttribute("data-r")); + if (r <= 0 || r >= rows) { + el.textContent = ""; + el.classList.remove("is-active"); + return; + } + el.textContent = r === R ? String(r) : String(Math.abs(r - R)); + el.classList.toggle("is-active", r === R); + }); + + const colNums = mazeDiv.querySelectorAll(".number.col[data-c]"); + colNums.forEach((el) => { + const c = Number(el.getAttribute("data-c")); + if (c <= 0 || c >= cols) { + el.textContent = ""; + el.classList.remove("is-active"); + return; + } + el.textContent = c === C ? String(c) : String(Math.abs(c - C)); + el.classList.toggle("is-active", c === C); + }); + + mazeDiv.classList.add("is-relative"); + }; + + useEffect(() => { + console.log('gameStatus', gameStatus); + const container = containerRef.current; + if (!['started', 'has-key'].includes(gameStatus)) return; + if (!container) return; + + const mazeDiv = container.querySelector("#maze") as HTMLElement | null; + if (!mazeDiv) return; + + mazeDiv.querySelectorAll(".hero").forEach((el) => el.classList.remove("hero")); + + const selector = `.maze-row > div[data-r="${playerPos.row}"][data-c="${playerPos.col}"]`; + const cell = mazeDiv.querySelector(selector) as HTMLElement | null; + if (cell) cell.classList.add("hero"); + + if (relative) { + mazeDiv.dataset.rows = String(mazeDiv.querySelectorAll(".maze-row").length); + mazeDiv.dataset.cols = String( + mazeDiv + .querySelector(".maze-row > div[data-r][data-c]") + ?.parentElement?.querySelectorAll(':scope > div[data-r][data-c]').length || 0 + ); + applyRelativeNumbers(mazeDiv, playerPos.row, playerPos.col); + } + }, [gameStatus, playerPos, containerRef, relative]); +} + +export type UseHeroRenderType = ReturnType; diff --git a/src/useKeyBindings/useKeyBindings.ts b/src/useKeyBindings/useKeyBindings.ts index 7389330..6b106e3 100644 --- a/src/useKeyBindings/useKeyBindings.ts +++ b/src/useKeyBindings/useKeyBindings.ts @@ -56,7 +56,7 @@ export const useKeyBindings = ({ cursor, gameStatus }: UseKeyBindingsParams) => return; } - const isDigit = ev.key >= "0" && e.key <= "9"; + const isDigit = ev.key >= "0" && ev.key <= "9"; if (isDigit) { if (ev.key === "0" && cursor.getCount() === "") return; recordKey(ev.key); @@ -71,7 +71,7 @@ export const useKeyBindings = ({ cursor, gameStatus }: UseKeyBindingsParams) => } if (ev.key === "^" || ev.key === "$") { - recordKey(e.key); + recordKey(ev.key); cursor.resetCount(); if (ev.key === "^") { cursor.moveToStart();