snake moving, changing directions, wall collision working

This commit is contained in:
2025-10-16 13:30:26 +01:00
parent 20ac6b9349
commit f37605d8d2
2 changed files with 88 additions and 1 deletions
+44 -1
View File
@@ -1,8 +1,10 @@
import { useState } from "react";
import { useState, useEffect, useRef } from "react";
import type { GameStatus } from "../types";
import type { UseRendererType } from "./useRenderer";
import type { UseSnakeType } from "./useSnake";
const INITIAL_SPEED = 200;
export function useGameStatus(
rendererManager: UseRendererType,
snakeManager: UseSnakeType
@@ -10,6 +12,10 @@ export function useGameStatus(
const { containerRef } = rendererManager;
const { initSnake, clearSnake } = snakeManager;
const [gameStatus, setGameStatus] = useState<GameStatus>("waiting");
const gameLoopRef = useRef<ReturnType<typeof setInterval> | null>(null);
const snakeManagerRef = useRef(snakeManager);
snakeManagerRef.current = snakeManager;
const startGame = () => {
initSnake();
@@ -17,6 +23,10 @@ export function useGameStatus(
};
const stopGame = () => {
if (gameLoopRef.current) {
clearInterval(gameLoopRef.current);
gameLoopRef.current = null;
}
clearSnake();
setGameStatus("waiting");
const container = containerRef.current;
@@ -25,6 +35,39 @@ export function useGameStatus(
});
};
useEffect(() => {
console.log("useGameStatus effect - gameStatus:", gameStatus);
if (gameStatus === "started") {
console.log("Starting game loop");
gameLoopRef.current = setInterval(() => {
console.log("Game loop tick");
const result = snakeManagerRef.current.moveSnake();
console.log("Move result:", result);
if (result === "wall-collision") {
setGameStatus("game-over");
}
}, INITIAL_SPEED);
return () => {
console.log("Cleaning up game loop");
if (gameLoopRef.current) {
clearInterval(gameLoopRef.current);
gameLoopRef.current = null;
}
};
}
}, [gameStatus]);
useEffect(() => {
if (gameStatus === "game-over") {
if (gameLoopRef.current) {
clearInterval(gameLoopRef.current);
gameLoopRef.current = null;
}
}
}, [gameStatus]);
return {
gameStatus,
setGameStatus,
+44
View File
@@ -9,6 +9,7 @@ export function useSnake(
) {
const { containerRef } = rendererManager;
const [snakeBody, setSnakeBody] = useState<SnakeBody>([]);
const snakeBodyRef = useRef<SnakeBody>([]);
const [direction, setDirection] = useState<Direction>("up");
const directionRef = useRef<Direction>("up");
@@ -23,6 +24,7 @@ export function useSnake(
];
setSnakeBody(initialBody);
snakeBodyRef.current = initialBody;
setDirection("up");
directionRef.current = "up";
renderSnake(initialBody);
@@ -30,6 +32,7 @@ export function useSnake(
const clearSnake = () => {
setSnakeBody([]);
snakeBodyRef.current = [];
setDirection("up");
directionRef.current = "up";
};
@@ -66,13 +69,54 @@ export function useSnake(
}
};
const moveSnake = (): "continue" | "wall-collision" | "self-collision" => {
const body = snakeBodyRef.current;
if (body.length === 0) return "continue";
const head = body[0];
const dir = directionRef.current;
let newR = head.r;
let newC = head.c;
switch (dir) {
case "up":
newR -= 1;
break;
case "down":
newR += 1;
break;
case "left":
newC -= 1;
break;
case "right":
newC += 1;
break;
}
if (newR < 0 || newR >= rows || newC < 0 || newC >= cols) {
return "wall-collision";
}
const newHead = { r: newR, c: newC };
const newBody = [newHead, ...body.slice(0, -1)];
setSnakeBody(newBody);
snakeBodyRef.current = newBody;
renderSnake(newBody);
return "continue";
};
return {
snakeBody,
snakeBodyRef,
direction,
directionRef,
initSnake,
clearSnake,
changeDirection,
moveSnake,
renderSnake,
};
}