feat: add maxLevel to GameOptions with default of 25
- New option: maxLevel (defaults to 25)
- Once a player reaches maxLevel, levels no longer progress
- Prevents unlimited level scaling and FPS increases
- Example: useGame({ maxLevel: 10 })
This commit is contained in:
+4
-3
@@ -3,7 +3,8 @@ import "@vimazing/vim-snake/game.css";
|
|||||||
import { useKeyBindings } from "./useKeyBindings";
|
import { useKeyBindings } from "./useKeyBindings";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { containerRef, gameStatus, scoreManager, keyLog, score, level } = useGame({}, useKeyBindings);
|
const gameManager = useGame({ startingLevel: 10 }, useKeyBindings);
|
||||||
|
const { containerRef, gameStatus, scoreManager, score, level } = gameManager;
|
||||||
|
|
||||||
const formatTime = (ms: number) => {
|
const formatTime = (ms: number) => {
|
||||||
const seconds = Math.floor(ms / 1000);
|
const seconds = Math.floor(ms / 1000);
|
||||||
@@ -15,7 +16,7 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<div className="relative mx-auto my-4 w-fit space-y-4">
|
<div className="relative mx-auto my-4 w-fit space-y-4">
|
||||||
<h1 className="text-2xl font-bold text-center">VIMazing Snake</h1>
|
<h1 className="text-2xl font-bold text-center">VIMazing Snake</h1>
|
||||||
|
|
||||||
<div className="flex gap-4 justify-center text-sm font-mono">
|
<div className="flex gap-4 justify-center text-sm font-mono">
|
||||||
<div className="px-3 py-1 bg-muted rounded">
|
<div className="px-3 py-1 bg-muted rounded">
|
||||||
Time: {formatTime(scoreManager.timeValue)}
|
Time: {formatTime(scoreManager.timeValue)}
|
||||||
@@ -37,7 +38,7 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ref={containerRef} className="relative" />
|
<div ref={containerRef} className="relative" />
|
||||||
|
|
||||||
<div className="text-center text-sm text-muted-foreground">
|
<div className="text-center text-sm text-muted-foreground">
|
||||||
{gameStatus === "waiting" && <p>Press <kbd className="px-2 py-1 bg-muted rounded">space</kbd> to start</p>}
|
{gameStatus === "waiting" && <p>Press <kbd className="px-2 py-1 bg-muted rounded">space</kbd> to start</p>}
|
||||||
{gameStatus === "started" && <p>Use <kbd className="px-2 py-1 bg-muted rounded">hjkl</kbd> to change direction • Press <kbd className="px-2 py-1 bg-muted rounded">q</kbd> to quit</p>}
|
{gameStatus === "started" && <p>Use <kbd className="px-2 py-1 bg-muted rounded">hjkl</kbd> to change direction • Press <kbd className="px-2 py-1 bg-muted rounded">q</kbd> to quit</p>}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export type GameOptions = {
|
|||||||
timeLimit?: number;
|
timeLimit?: number;
|
||||||
startingLevel?: number;
|
startingLevel?: number;
|
||||||
foodsPerLevel?: number;
|
foodsPerLevel?: number;
|
||||||
|
maxLevel?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useKeyBindings, type UseKeyBindingsType } from "./useKeyBindings";
|
|||||||
import { useScore } from "../useScore";
|
import { useScore } from "../useScore";
|
||||||
|
|
||||||
export function useGame(options?: GameOptions, platformHook?: unknown): GameManager {
|
export function useGame(options?: GameOptions, platformHook?: unknown): GameManager {
|
||||||
const { cols = 30, rows = 20, startingLevel, foodsPerLevel } = options ?? {};
|
const { cols = 30, rows = 20, startingLevel, foodsPerLevel, maxLevel } = options ?? {};
|
||||||
|
|
||||||
const boardManager = useBoard();
|
const boardManager = useBoard();
|
||||||
const { containerRef, renderBoard } = boardManager;
|
const { containerRef, renderBoard } = boardManager;
|
||||||
@@ -18,7 +18,7 @@ export function useGame(options?: GameOptions, platformHook?: unknown): GameMana
|
|||||||
|
|
||||||
const foodManager = useFood(cols, rows, boardManager);
|
const foodManager = useFood(cols, rows, boardManager);
|
||||||
|
|
||||||
const gameManager = useGameStatus(boardManager, snakeManager, foodManager, { startingLevel, foodsPerLevel });
|
const gameManager = useGameStatus(boardManager, snakeManager, foodManager, { startingLevel, foodsPerLevel, maxLevel });
|
||||||
const { gameStatus, setGameStatus, startGame, quitGame, togglePause, score, level } = gameManager;
|
const { gameStatus, setGameStatus, startGame, quitGame, togglePause, score, level } = gameManager;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type { UseFoodType } from "../useGame/useFood";
|
|||||||
export type UseGameStatusParams = {
|
export type UseGameStatusParams = {
|
||||||
startingLevel?: number;
|
startingLevel?: number;
|
||||||
foodsPerLevel?: number;
|
foodsPerLevel?: number;
|
||||||
|
maxLevel?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useGameStatus(
|
export function useGameStatus(
|
||||||
@@ -17,6 +18,7 @@ export function useGameStatus(
|
|||||||
) {
|
) {
|
||||||
const startingLevel = params?.startingLevel ?? 1;
|
const startingLevel = params?.startingLevel ?? 1;
|
||||||
const foodsPerLevel = params?.foodsPerLevel ?? 10;
|
const foodsPerLevel = params?.foodsPerLevel ?? 10;
|
||||||
|
const maxLevel = params?.maxLevel ?? 25;
|
||||||
const { containerRef } = boardManager;
|
const { containerRef } = boardManager;
|
||||||
const { initSnake, clearSnake, snakeBodyRef } = snakeManager;
|
const { initSnake, clearSnake, snakeBodyRef } = snakeManager;
|
||||||
const { spawnFood, clearFood } = foodManager;
|
const { spawnFood, clearFood } = foodManager;
|
||||||
@@ -99,7 +101,7 @@ export function useGameStatus(
|
|||||||
const pointsToAdd = levelRef.current;
|
const pointsToAdd = levelRef.current;
|
||||||
|
|
||||||
// Update level OUTSIDE of setScore to avoid multiple triggers
|
// Update level OUTSIDE of setScore to avoid multiple triggers
|
||||||
if (willLevelUp) {
|
if (willLevelUp && levelRef.current < maxLevel) {
|
||||||
const newLevel = levelRef.current + 1;
|
const newLevel = levelRef.current + 1;
|
||||||
levelRef.current = newLevel;
|
levelRef.current = newLevel;
|
||||||
setLevel(newLevel);
|
setLevel(newLevel);
|
||||||
|
|||||||
Reference in New Issue
Block a user