From f37605d8d244ed25d359fb9169c2f5645df330e6 Mon Sep 17 00:00:00 2001 From: Andre Padez Date: Thu, 16 Oct 2025 13:30:26 +0100 Subject: [PATCH] snake moving, changing directions, wall collision working --- src/useGame/useGameStatus.ts | 45 +++++++++++++++++++++++++++++++++++- src/useGame/useSnake.ts | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/useGame/useGameStatus.ts b/src/useGame/useGameStatus.ts index 1398730..22c87cd 100755 --- a/src/useGame/useGameStatus.ts +++ b/src/useGame/useGameStatus.ts @@ -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("waiting"); + const gameLoopRef = useRef | 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, diff --git a/src/useGame/useSnake.ts b/src/useGame/useSnake.ts index d4d5fae..d7734fc 100755 --- a/src/useGame/useSnake.ts +++ b/src/useGame/useSnake.ts @@ -9,6 +9,7 @@ export function useSnake( ) { const { containerRef } = rendererManager; const [snakeBody, setSnakeBody] = useState([]); + const snakeBodyRef = useRef([]); const [direction, setDirection] = useState("up"); const directionRef = useRef("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, }; }