Hi people,
I’m quite new to React, so my problem might be quite simple to fix. I’m building a snake game, where the snake and current direction are saved as state. A start button sets up the interval for updating the snake depending on the current direction, but … snake doesn’t want to update. I’m sure I’m missing something very basic. Here’s the relevant parts of code:
function Game(){
const size = 15;
const [snake, setSnake] = useState([95,94,93]);
const [dir, setDir] = useState('right');
const [gameInterval, setGameInterval] = useState([]);
const [isGameRunning, setIsGameRunning] = useState(false);
// add keyboard event listener on first render
useEffect(()=>{
document.addEventListener('keyup', handleKeyUp);
return ()=>document.removeEventListener('keyup', handleKeyUp)
},[]);
function handleKeyUp(e){
let newDir;
if (e.keyCode === 37){
newDir = 'left';
} else if (e.keyCode === 38){
newDir = 'up';
} else if (e.keyCode === 39){
newDir = 'right';
} else if (e.keyCode === 40){
newDir = 'down';
} else {
return;
};
setDir(newDir);
};
// toggle game on/off
function handleStartBtn(){
if (!isGameRunning){
setIsGameRunning(true);
if (gameInterval.length === 0){
// moveSnake gets called every 800ms,
// but doesn't update the snake
let interval = setInterval(moveSnake, 800);
setGameInterval([...gameInterval, interval])
}
} else if (isGameRunning){
setIsGameRunning(false);
if (gameInterval.length !== 0){
gameInterval.forEach(int => clearInterval(int));
setGameInterval([]);
}
}
}
function moveSnake(){
let newSnake = [...snake];
console.log(newSnake)
// this always logs the original position of the snake on every run
let head = newSnake[0];
newSnake.pop();
if (dir === 'right'){
head += 1;
} else if (dir === 'left'){
head -= 1;
} else if (dir === 'up'){
head -= size;
} else if (dir === 'down'){
head += size;
};
newSnake.unshift(head);
console.log(newSnake)
// this logs the correct new position of the snake
setSnake(newSnake);
}
// render stuff
const boardVals = {size, apple, snake};
const btnDisplay = isGameRunning ? 'Stop' : 'Start';
return (
<div id="game">
<Board vals={boardVals}/>
<div>
// I'm rendering state to check what's happening:
// Here, snake gets updated correctly. But only once.
{snake.map((segment,i) => <span key={i}>{segment} </span>)}
<p>{dir}</p>
<button className="btn" onClick={handleStartBtn}>{btnDisplay}</button>
</div>
</div>
)
}
export default Game;
Any hints are most welcome, I don’t even know what to google anymore…
(First time posting btw, so hello )