Last updated on August 11, 2024 pm
网页端的贪吃蛇小游戏,支持定制,目前功能尚少
index.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <!DOCTYPE html > <html lang ="en" > <head > <link rel ="stylesheet" href ="style.css" /> <meta charset ="UTF-8" /> <meta name ="viewport" content ="width=device-width, initial-scale=1.0" /> <meta http-equiv ="X-UA-Compatible" content ="ie=edge" /> <title > Snake</title > <script src ="snake.js" > </script > <script src ="input.js" > </script > <script src ="food.js" > </script > <script src ="snakeUtils.js" > </script > <script src ="game.js" defer > </script > </head > <body > <div id ="game-board" > </div > <div id ="game-start" > <h1 > Start Game</h1 > <button id ="start-button" > Start</button > </div > <div id ="game-over" > <h1 > Game Over</h1 > <button id ="restart-button" > Restart</button > </div > </body > </html >
style.css 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 body { height : 100vh ; width : 100vw ; display : flex; justify-content : center; align-items : center; margin : 0 ; background-color : gray; }#game-board { background-color : black; width : 100vmin ; height : 100vmin ; display : grid; grid-template-rows : repeat (21 , 1 fr); grid-template-columns : repeat (21 , 1 fr); }.snake { background-image : url ('IMG_20240731_162343.jpg' ); background-size : 4.76vmin 4.76vmin ; background-position : center; }.food { background-image : url ('th.jpg' ); background-size : 4.76vmin 4.76vmin ; }#game-start , #game-over { position : absolute; top : 50% ; left : 50% ; transform : translate (-50% , -50% ); display : flex; justify-content : center; align-items : center; flex-direction : column; background-color : rgba (0 , 0 , 0 , 0.8 ); color : white; padding : 20px ; border-radius : 10px ; text-align : center; z-index : 1000 ; }#game-start { display : flex; }#game-over { display : none; }button { margin-top : 20px ; padding : 10px 20px ; font-size : 16px ; }
game.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 const SNAKE_SPEED = 5 ;const gameBoard = document .getElementById ('game-board' );const gameStartOverlay = document .getElementById ('game-start' );const gameOverOverlay = document .getElementById ('game-over' );let isGameRunning = false ;let gameInterval;const init = ( ) => { document .getElementById ('start-button' ).addEventListener ('click' , startGame); document .getElementById ('restart-button' ).addEventListener ('click' , restartGame); };window .onload = init;const main = ( ) => { if (!isGameRunning) return ; update (); draw (); if (checkGameOver ()) { gameOver (); } };const startGame = ( ) => { console .log ('Starting game...' ); isGameRunning = true ; gameStartOverlay.style .display = 'none' ; gameOverOverlay.style .display = 'none' ; gameBoard.innerHTML = '' ; resetGame (); if (gameInterval) clearInterval (gameInterval); gameInterval = setInterval (main, 1000 / SNAKE_SPEED ); };const restartGame = ( ) => { console .log ('Restarting game...' ); isGameRunning = true ; gameOverOverlay.style .display = 'none' ; gameBoard.innerHTML = '' ; resetGame (); if (gameInterval) clearInterval (gameInterval); gameInterval = setInterval (main, 1000 / SNAKE_SPEED ); };const gameOver = ( ) => { console .log ('Game Over' ); isGameRunning = false ; clearInterval (gameInterval); gameOverOverlay.style .display = 'block' ; };const update = ( ) => { console .log ('Updating' ); updateSnake (); updateFood (); };const draw = ( ) => { gameBoard.innerHTML = '' ; drawSnake (gameBoard); drawFood (gameBoard); };const checkGameOver = ( ) => { return snakeOutOfBounds () || snakeIntersectSelf (); };const resetGame = ( ) => { snakeBody = [ { x : 11 , y : 11 }, { x : 11 , y : 10 }, { x : 11 , y : 9 } ]; food = getNewFoodPosition (); };
food.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let food = { x : 4 , y : 16 };const updateFood = ( ) => { if (onSnake (food)) { growSnake (); food = getNewFoodPosition (); } };const drawFood = (gameBoard ) => { const foodElement = document .createElement ('div' ); foodElement.style .gridRowStart = food.y ; foodElement.style .gridColumnStart = food.x ; foodElement.classList .add ('food' ); gameBoard.appendChild (foodElement); };
snake.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 let snakeBody = [ { x : 11 , y : 11 }, { x : 11 , y : 10 }, { x : 11 , y : 9 }, ];const updateSnake = ( ) => { snakeBody.pop (); const newHead = { ...snakeBody[0 ] }; const snakeDirection = getInputDirection (); newHead.x += snakeDirection.x ; newHead.y += snakeDirection.y ; if (outOfBounds (newHead)) { gameOver (); return ; } snakeBody.unshift (newHead); };const drawSnake = (gameBoard ) => { for (let i = 0 ; i < snakeBody.length ; i++) { const segment = snakeBody[i]; const snakeElement = document .createElement ('div' ); snakeElement.style .gridRowStart = segment.y ; snakeElement.style .gridColumnStart = segment.x ; snakeElement.classList .add ('snake' ); gameBoard.appendChild (snakeElement); } };
snakeUtils.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 const GRID_SIZE = 21 ;const onSnake = (position ) => { for (let i = 0 ; i < snakeBody.length ; i++) { if (equalPositions (position, snakeBody[i])) { return true ; } } return false ; };const equalPositions = (pos1, pos2 ) => { return pos1.x === pos2.x && pos1.y === pos2.y ; };const growSnake = ( ) => { snakeBody.push ({ ...snakeBody[snakeBody.length - 1 ] }); };const getNewFoodPosition = ( ) => { let randomFoodPosition = randomGridPosition (); while (onSnake (randomFoodPosition)) { randomFoodPosition = randomGridPosition (); } return randomFoodPosition; };const randomGridPosition = ( ) => { return { x : Math .floor (Math .random () * GRID_SIZE ) + 1 , y : Math .floor (Math .random () * GRID_SIZE ) + 1 , }; };const outOfBounds = (position ) => { return position.x < 1 || position.x > GRID_SIZE || position.y < 1 || position.y > GRID_SIZE ; }const snakeOutOfBounds = ( ) => { return outOfBounds (snakeBody[0 ]); }const snakeIntersectSelf = ( ) => { for (let i = 1 ; i < snakeBody.length ; i++) { if (equalPositions (snakeBody[0 ], snakeBody[i])) { return true ; } } return false ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 let inputDirection = { x : 0 , y : 1 };window .addEventListener ('keydown' , (event ) => { if (event.key === 'ArrowUp' && inputDirection.x !== 0 ) { inputDirection = { x : 0 , y : -1 }; } else if (event.key === 'ArrowDown' && inputDirection.x !== 0 ) { inputDirection = { x : 0 , y : 1 }; } else if (event.key === 'ArrowRight' && inputDirection.y !== 0 ) { inputDirection = { x : 1 , y : 0 }; } else if (event.key === 'ArrowLeft' && inputDirection.y !== 0 ) { inputDirection = { x : -1 , y : 0 }; } });const getInputDirection = ( ) => { return inputDirection; };
web开发课程4--贪吃蛇小游戏
http://example.com/2024/08/07/2024-08-07-web开发课程4--贪吃蛇小游戏/