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