useGame=>useCursor=>useHero=>useHeroRender
This commit is contained in:
@@ -25,12 +25,6 @@ export const useKeyBindings = (gameManager: GameManager) => {
|
||||
// ignore other keys while waiting
|
||||
if (gameStatus === "waiting") return;
|
||||
|
||||
// cancel count or stop game
|
||||
if (ev.key === "Escape") {
|
||||
quitGame();
|
||||
return;
|
||||
}
|
||||
|
||||
// quit
|
||||
if (ev.key === "q" || ev.key === "Q") {
|
||||
quitGame();
|
||||
|
||||
@@ -69,6 +69,12 @@ export type GameStatusManager = {
|
||||
|
||||
//Cursor Stuff
|
||||
export type CursorMode = 'normal' | 'insert' | 'replace' | 'visual' | 'visual-line';
|
||||
export type UseHeroType = {
|
||||
heroPos: Coord | null;
|
||||
setHeroPos: (pos: Coord | null) => void;
|
||||
moveHero: (dr: number, dc: number, steps: number, gameStatus: GameStatus, setGameStatus: (s: GameStatus) => void) => void;
|
||||
};
|
||||
|
||||
export type Cursor = { //return type of useCursor (currently useHero)
|
||||
position: () => Coord;
|
||||
mode: () => CursorMode;
|
||||
@@ -87,4 +93,5 @@ export type Cursor = { //return type of useCursor (currently useHero)
|
||||
setCount: (digit: string) => void;
|
||||
setLastKey: (key: string) => void;
|
||||
getLastKey: () => string;
|
||||
hero?: UseHeroType;
|
||||
}
|
||||
|
||||
@@ -229,12 +229,12 @@ export class MazeGenerator {
|
||||
});
|
||||
});
|
||||
|
||||
return [fr, fc];
|
||||
return { row: fr, col: fc };
|
||||
}
|
||||
|
||||
placeKey(): void {
|
||||
const [fr, fc] = this.getKeyLocation();
|
||||
this.maze[fr][fc] = ["key"];
|
||||
const keyLocation = this.getKeyLocation();
|
||||
this.maze[keyLocation.row][keyLocation.col] = ["key"];
|
||||
}
|
||||
|
||||
shortestPath(
|
||||
@@ -250,14 +250,14 @@ export class MazeGenerator {
|
||||
} else {
|
||||
for (let r = 0; r < this.rows; r++) {
|
||||
for (let c = 0; c < this.cols; c++) {
|
||||
if (this.maze[r][c].includes(fromTag)) start = [r, c];
|
||||
if (this.maze[r][c].includes(fromTag)) start = { row: r, col: c };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let r = 0; r < this.rows; r++) {
|
||||
for (let c = 0; c < this.cols; c++) {
|
||||
if (this.maze[r][c].includes(toTag)) end = [r, c];
|
||||
if (this.maze[r][c].includes(toTag)) end = { row: r, col: c };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,39 +265,41 @@ export class MazeGenerator {
|
||||
|
||||
const visited = this.initArray<boolean>(false);
|
||||
const prev = this.initArray<Coord | null>(null);
|
||||
const queue: Coord[] = [[...start]];
|
||||
visited[start[0]][start[1]] = true;
|
||||
const queue: Coord[] = [start];
|
||||
visited[start.row][start.col] = true;
|
||||
|
||||
const dirs: Coord[] = [
|
||||
[-1, 0],
|
||||
[1, 0],
|
||||
[0, -1],
|
||||
[0, 1],
|
||||
{ row: -1, col: 0 },
|
||||
{ row: 1, col: 0 },
|
||||
{ row: 0, col: -1 },
|
||||
{ row: 0, col: 1 },
|
||||
];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const [r, c] = queue.shift() as Coord;
|
||||
const current = queue.shift()!;
|
||||
const r = current.row;
|
||||
const c = current.col;
|
||||
|
||||
if (r === end[0] && c === end[1]) {
|
||||
if (r === end.row && c === end.col) {
|
||||
const path: Coord[] = [];
|
||||
let curr: Coord | null = end;
|
||||
while (curr) {
|
||||
path.unshift(curr);
|
||||
curr = prev[curr[0]][curr[1]];
|
||||
curr = prev[curr.row][curr.col];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
for (const [dr, dc] of dirs) {
|
||||
const nr = r + dr,
|
||||
nc = c + dc;
|
||||
for (const dir of dirs) {
|
||||
const nr = r + dir.row,
|
||||
nc = c + dir.col;
|
||||
if (!this.inBounds(nr, nc)) continue;
|
||||
if (visited[nr][nc]) continue;
|
||||
if (this.maze[nr][nc].includes("wall")) continue;
|
||||
|
||||
visited[nr][nc] = true;
|
||||
prev[nr][nc] = [r, c];
|
||||
queue.push([nr, nc]);
|
||||
prev[nr][nc] = { row: r, col: c };
|
||||
queue.push({ row: nr, col: nc });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export * from './useCursor';
|
||||
export * from './useHero';
|
||||
export * from './useHeroRender';
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import { useRef } from 'react'
|
||||
import type { CursorMode, Coord, BoardManager } from '../types'
|
||||
import type { CursorMode, Coord, BoardManager, GameStatus } from '../types'
|
||||
import { useHero } from './useHero'
|
||||
|
||||
type Motion = { dr: number; dc: number; steps: number };
|
||||
|
||||
export function useCursor(board: BoardManager) {
|
||||
export function useCursor(board: BoardManager, gameStatus: GameStatus) {
|
||||
const position = useRef<Coord>({ row: 0, col: 0 })
|
||||
const mode = useRef<CursorMode>('normal')
|
||||
const countRef = useRef<string>("");
|
||||
const lastMotionRef = useRef<Motion | null>(null);
|
||||
const lastKeyRef = useRef<string>("");
|
||||
|
||||
const hero = useHero(board, gameStatus);
|
||||
|
||||
function findAnchorTarget(dir: "left" | "right") {
|
||||
const m = board.mazeRef.current;
|
||||
const pos = position.current;
|
||||
@@ -209,7 +212,7 @@ export function useCursor(board: BoardManager) {
|
||||
return lastKeyRef.current;
|
||||
}
|
||||
|
||||
return {
|
||||
const cursorAPI = {
|
||||
position: () => position.current,
|
||||
mode: () => mode.current,
|
||||
move,
|
||||
@@ -228,5 +231,7 @@ export function useCursor(board: BoardManager) {
|
||||
setLastKey,
|
||||
getLastKey,
|
||||
}
|
||||
|
||||
return cursorAPI;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,29 +8,6 @@ export function useHero(board: BoardManager, gameStatus: GameStatus) {
|
||||
|
||||
const animatingRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (gameStatus === 'started' && !heroPos) {
|
||||
const m = mazeRef.current;
|
||||
if (!m.length) return;
|
||||
|
||||
for (let c = 0; c < m[0].length; c++) {
|
||||
if (m[m.length - 1][c].includes("entrance")) {
|
||||
setHeroPos({ row: m.length - 1, col: c });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [gameStatus, heroPos, mazeRef]);
|
||||
|
||||
useEffect(() => {
|
||||
if (gameStatus === 'waiting' || gameStatus === 'game-over' || gameStatus === 'game-won') {
|
||||
setHeroPos(null);
|
||||
const container = containerRef.current;
|
||||
container?.querySelector("#maze")?.classList.remove("finished");
|
||||
container?.querySelectorAll(".hero").forEach((el) => el.classList.remove("hero"));
|
||||
}
|
||||
}, [gameStatus, containerRef]);
|
||||
|
||||
const getCellEl = useCallback((r: number, c: number): HTMLElement | null => {
|
||||
const container = containerRef.current;
|
||||
if (!container) return null;
|
||||
@@ -61,6 +38,29 @@ export function useHero(board: BoardManager, gameStatus: GameStatus) {
|
||||
return () => window.removeEventListener("maze-invalid", onInvalid);
|
||||
}, [flashInvalid]);
|
||||
|
||||
useEffect(() => {
|
||||
if (gameStatus === 'started' && !heroPos) {
|
||||
const m = mazeRef.current;
|
||||
if (!m.length) return;
|
||||
|
||||
for (let c = 0; c < m[0].length; c++) {
|
||||
if (m[m.length - 1][c].includes("entrance")) {
|
||||
setHeroPos({ row: m.length - 1, col: c });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [gameStatus, heroPos, mazeRef]);
|
||||
|
||||
useEffect(() => {
|
||||
if (gameStatus === 'waiting' || gameStatus === 'game-over' || gameStatus === 'game-won') {
|
||||
setHeroPos(null);
|
||||
const container = containerRef.current;
|
||||
container?.querySelector("#maze")?.classList.remove("finished");
|
||||
container?.querySelectorAll(".hero").forEach((el) => el.classList.remove("hero"));
|
||||
}
|
||||
}, [gameStatus, containerRef]);
|
||||
|
||||
const moveHero = useCallback(
|
||||
(
|
||||
dr: number,
|
||||
@@ -204,7 +204,6 @@ export function useHero(board: BoardManager, gameStatus: GameStatus) {
|
||||
moveHero,
|
||||
};
|
||||
|
||||
console.log('calling useHeroRender with', { gameStatus, board, hero });
|
||||
useHeroRender({ gameStatus, board, hero });
|
||||
|
||||
return hero;
|
||||
+1
-3
@@ -1,7 +1,6 @@
|
||||
import type { GameManager, GameOptions } from './types';
|
||||
import { useBoard } from './useBoard';
|
||||
import { useCursor } from './useCursor';
|
||||
import { useHero } from './useHero';
|
||||
import { useKeyBindings } from './useKeyBindings';
|
||||
import { useGameStatus } from './useGameStatus';
|
||||
|
||||
@@ -9,12 +8,11 @@ export function useGame(options: GameOptions, platformHook?: unknown): GameManag
|
||||
const { cols, rows } = options;
|
||||
const board = useBoard(cols, rows);
|
||||
const { containerRef, renderBoard } = board;
|
||||
const cursor = useCursor(board);
|
||||
const gameStatusManager = useGameStatus();
|
||||
|
||||
const { gameStatus, startGame, togglePause, quitGame } = gameStatusManager;
|
||||
|
||||
const hero = useHero(board, gameStatus);
|
||||
const cursor = useCursor(board, gameStatus);
|
||||
const keyManager = useKeyBindings({ cursor, gameStatus });
|
||||
|
||||
const gameManager = {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './useHero';
|
||||
export * from './useHeroRender';
|
||||
Reference in New Issue
Block a user