diff --git a/example/src/App.tsx b/example/src/App.tsx index 6edfe27..cb89a9a 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,4 +1,4 @@ -import { useGame } from "../../src/useGame"; +import { useGame, version } from "../../src"; import { useKeyBindings } from "./useKeyBindings"; import { useIsMobile } from "./useIsMobile"; import '../../src/game.css'; @@ -10,7 +10,7 @@ function App() { const gameManager = useGame({ cols, rows }, useKeyBindings); const { containerRef, gameStatus, scoreManager } = gameManager; - const { timeValue, keystrokes, efficiency, optimalSteps, finalScore } = scoreManager; + const { timeValue, keystrokes, finalScore } = scoreManager; const formatTime = (ms: number) => { const seconds = Math.floor(ms / 1000); @@ -21,7 +21,7 @@ function App() { return (
-

VIMazing vim-maze example

+

VIMazing vim-maze v{version} example

{(gameStatus === "started" || gameStatus === "has-key" || gameStatus === "game-won") && (
@@ -33,16 +33,6 @@ function App() {
Keystrokes
{keystrokes}
-
-
Efficiency
-
150 ? 'text-red-500' : efficiency > 100 ? 'text-yellow-500' : 'text-green-500'}`}> - {efficiency}% -
-
-
-
Optimal
-
{optimalSteps}
-
{gameStatus === "game-won" && finalScore && ( <>
diff --git a/src/index.ts b/src/index.ts index 110e6c9..9d104fc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,4 +2,6 @@ export * from './types'; export * from './useGame'; export * from './useGameStatus'; export { gameInfo } from './gameInfo'; +import { version } from '../package.json'; export type { GameInfo } from './gameInfo'; +export { version }; diff --git a/src/useCursor/useCursor.ts b/src/useCursor/useCursor.ts index dda5b6c..b2e40d3 100644 --- a/src/useCursor/useCursor.ts +++ b/src/useCursor/useCursor.ts @@ -1,7 +1,6 @@ import { useRef, useEffect } from 'react' import type { CursorMode, Coord } from './types'; -import type { BoardManager } from '../useBoard/types'; -import type { GameStatusManager } from '../useGameStatus/types'; +import type { GameStatusManager, BoardManager, CellTag } from '../types'; import { useHero } from './useHero'; import { useGameKeys } from './useGameKeys'; import { useMazeNavigation } from '../useBoard'; @@ -16,6 +15,9 @@ export function useCursor(board: BoardManager, gameStatusManager: GameStatusMana const navigator = useMazeNavigation(board.mazeRef.current); const vimMotions = useVimMotions(); + const maze = board.mazeInstanceRef.current?.maze; + const exitPos = maze?.[0].findIndex((cell: CellTag) => cell.includes('door')); + // Sync cursor position with hero position useEffect(() => { if (hero.heroPos) { @@ -61,98 +63,101 @@ export function useCursor(board: BoardManager, gameStatusManager: GameStatusMana move(0, 1, count); } - function moveToAnchor(target: 'start' | 'end' | 'top' | 'bottom'): void { - const currentPos = position.current; - const direction = target === 'start' ? 'left' : - target === 'end' ? 'right' : - target === 'top' ? 'top' : 'bottom'; + function moveToAnchor(target: 'start' | 'end' | 'top' | 'bottom'): void { + const currentPos = position.current; + const direction = target === 'start' ? 'left' : + target === 'end' ? 'right' : + target === 'top' ? 'top' : 'bottom'; - const hasKey = gameStatusManager.gameStatus === 'has-key'; - const anchorTarget = navigator.findAnchorTarget(currentPos, direction, hasKey); - if (!anchorTarget) return; + const hasKey = gameStatusManager.gameStatus === 'has-key'; + const anchorTarget = navigator.findAnchorTarget(currentPos, direction, hasKey); + if (!anchorTarget) return; - const dr = anchorTarget.row > currentPos.row ? 1 : - anchorTarget.row < currentPos.row ? -1 : 0; - const dc = anchorTarget.col > currentPos.col ? 1 : - anchorTarget.col < currentPos.col ? -1 : 0; - const steps = Math.abs(anchorTarget.row - currentPos.row) + Math.abs(anchorTarget.col - currentPos.col); + const dr = anchorTarget.row > currentPos.row ? 1 : + anchorTarget.row < currentPos.row ? -1 : 0; + const dc = anchorTarget.col > currentPos.col ? 1 : + anchorTarget.col < currentPos.col ? -1 : 0; + const steps = Math.abs(anchorTarget.row - currentPos.row) + Math.abs(anchorTarget.col - currentPos.col); - position.current = anchorTarget; - if (hero && hero.heroPos) { - hero.moveTo(anchorTarget); - if (steps > 0) { - vimMotions.setLastMotion({ dr, dc, steps }); - } - } - } + position.current = anchorTarget; + if (hero && hero.heroPos) { + hero.moveTo(anchorTarget); + if (steps > 0) { + vimMotions.setLastMotion({ dr, dc, steps }); + } + } + } - function moveToStart(): void { - const currentPos = position.current; - const target = navigator.findAnchorTarget(currentPos, 'left'); - if (!target) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; - const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; - const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); - if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - moveToAnchor('start'); - } + function moveToStart(): void { + const currentPos = position.current; + const target = navigator.findAnchorTarget(currentPos, 'left'); + if (!target) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; + const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; + const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); + if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + moveToAnchor('start'); + } - function moveToEnd(): void { - const currentPos = position.current; - const target = navigator.findAnchorTarget(currentPos, 'right'); - if (!target) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; - const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; - const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); - if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - moveToAnchor('end'); - } + function moveToEnd(): void { + const currentPos = position.current; + const target = navigator.findAnchorTarget(currentPos, 'right'); + if (!target) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; + const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; + const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); + if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + moveToAnchor('end'); + } - function moveToTop(): void { - const currentPos = position.current; - const target = navigator.findAnchorTarget(currentPos, 'top'); - if (!target) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; - const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; - const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); - if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - moveToAnchor('top'); - } + function moveToTop(): void { + const currentPos = position.current; - function moveToBottom(): void { - const currentPos = position.current; - const target = navigator.findAnchorTarget(currentPos, 'bottom'); - if (!target) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; - const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; - const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); - if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { - window.dispatchEvent(new Event("maze-invalid")); - return; - } - moveToAnchor('bottom'); - } + console.log("Exit position:", exitPos, currentPos); + console.log(currentPos, board); + const target = navigator.findAnchorTarget(currentPos, 'top'); + if (!target) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; + const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; + const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); + if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + moveToAnchor('top'); + } + + function moveToBottom(): void { + const currentPos = position.current; + const target = navigator.findAnchorTarget(currentPos, 'bottom'); + if (!target) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + const dr = target.row > currentPos.row ? 1 : target.row < currentPos.row ? -1 : 0; + const dc = target.col > currentPos.col ? 1 : target.col < currentPos.col ? -1 : 0; + const steps = Math.abs(target.row - currentPos.row) + Math.abs(target.col - currentPos.col); + if (!navigator.validatePath(currentPos, { row: dr, col: dc }, steps)) { + window.dispatchEvent(new Event("maze-invalid")); + return; + } + moveToAnchor('bottom'); + } function repeatLastMotion(): void { const motion = vimMotions.repeatLastMotion(); @@ -176,17 +181,17 @@ export function useCursor(board: BoardManager, gameStatusManager: GameStatusMana vimMotions.resetCount(); } - function getCount(): string { - return String(vimMotions.getCount()); - } + function getCount(): string { + return String(vimMotions.getCount()); + } - function hasCount(): boolean { - return vimMotions.hasCount(); - } + function hasCount(): boolean { + return vimMotions.hasCount(); + } - function setCount(digit: string): void { - vimMotions.processKey(digit); - } + function setCount(digit: string): void { + vimMotions.processKey(digit); + } function setLastKey(key: string): void { lastKeyRef.current = key; @@ -196,27 +201,27 @@ export function useCursor(board: BoardManager, gameStatusManager: GameStatusMana return lastKeyRef.current; } - const cursor = { - position: () => position.current, - mode: () => mode.current, - move, - moveLeft, - moveRight, - moveUp, - moveDown, - moveToStart, - moveToEnd, - moveToTop, - moveToBottom, - repeatLastMotion, - resetCount, - getCount, - hasCount, - setCount, - setLastKey, - getLastKey, - hero, - } + const cursor = { + position: () => position.current, + mode: () => mode.current, + move, + moveLeft, + moveRight, + moveUp, + moveDown, + moveToStart, + moveToEnd, + moveToTop, + moveToBottom, + repeatLastMotion, + resetCount, + getCount, + hasCount, + setCount, + setLastKey, + getLastKey, + hero, + } const keyManager = useGameKeys({ cursor, gameStatusManager }); diff --git a/src/useScore/useTimer.ts b/src/useScore/useTimer.ts index bf2d46c..668cb1f 100644 --- a/src/useScore/useTimer.ts +++ b/src/useScore/useTimer.ts @@ -8,17 +8,24 @@ export function useTimer(): TimerManager { const startTimeRef = useRef(null); const frameRef = useRef(null); const runningRef = useRef(false); + const lastUpdateRef = useRef(0); + const currentTimeRef = useRef(0); const startTimer = () => { if (runningRef.current) return; runningRef.current = true; startTimeRef.current = performance.now(); + lastUpdateRef.current = 0; const tick = () => { if (!runningRef.current) return; const now = performance.now(); const elapsed = now - (startTimeRef.current ?? now); - setTimeValue(elapsed); + currentTimeRef.current = elapsed; + if (elapsed - lastUpdateRef.current >= 1000) { + lastUpdateRef.current = elapsed; + setTimeValue(elapsed); + } frameRef.current = requestAnimationFrame(tick); }; @@ -26,6 +33,7 @@ export function useTimer(): TimerManager { }; const stopTimer = () => { + setTimeValue(currentTimeRef.current); runningRef.current = false; if (frameRef.current) { cancelAnimationFrame(frameRef.current); @@ -37,6 +45,7 @@ export function useTimer(): TimerManager { stopTimer(); setTimeValue(0); startTimeRef.current = null; + lastUpdateRef.current = 0; }; useEffect(() => { @@ -45,5 +54,7 @@ export function useTimer(): TimerManager { }; }, []); - return { timeValue, startTimer, stopTimer, resetTimer }; + console.log('timeValue', timeValue); + + return { timeValue, startTimer, stopTimer, resetTimer }; }