原生js实现贪吃蛇小游戏效果代码
代码语言:html
所属分类:游戏
代码描述:原生js实现贪吃蛇小游戏效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> html, body { height: 100%; margin: 0; } body { --size: 15px; --color: black; font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; color: var(--color); background-color: #ff8585; background: linear-gradient( 162deg, rgba(255, 133, 133, 1) 0%, rgba(227, 84, 95, 1) 100% ); } footer { font-size: 0.8em; } @media (min-height: 425px) { body { --size: 25px; } footer { height: 40px; font-size: 1em; } } .container { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100%; } header { display: flex; justify-content: space-between; width: calc(var(--size) *17); font-size: 2em; font-weight: 900; } .grid { display: grid; grid-template-columns: repeat(15, auto); grid-template-rows: repeat(15, auto); border: var(--size)solid var(--color); } .tile { position: relative; width: var(--size); height: var(--size); } .content { position: absolute; width: 100%; height: 100%; } footer { margin-top: 20px; max-width: calc(var(--size) *17); text-align: center; } footer a:visited { color: inherit; } </style> </head> <body translate="no"> <div class="container"> <header> <div class="contrast"> 100% </div> <div class="score"> 0 </div> </header> <div class="grid"></div> <footer> Press an arrow key or space to start! <div> Ready for hard more? Press H </div> </footer> </div> <script> // Follow me on twitter: https://twitter.com/HunorBorbely document.addEventListener("DOMContentLoaded", function (event) { // Game data let snakePositions; // An array of snake positions, starting head first let applePosition; // The position of the apple let startTimestamp; // The starting timestamp of the animation let lastTimestamp; // The previous timestamp of the animation let stepsTaken; // How many steps did the snake take let score; let contrast; let inputs; // A list of directions the snake still has to take in order let gameStarted = false; let hardMode = false; // Configuration const width = 15; // Grid width const height = 15; // Grid height const speed = 200; // Milliseconds it takes for the snake to take a step in the grid let fadeSpeed = 5000; // milliseconds it takes the grid to disappear (initially) let fadeExponential = 1.024; // after each score it will gradually take more time for the grid to fade const contrastIncrease = 0.5; // contrast you gain after each score const color = "black"; // Setup: Build up the grid // The grid consists of (width x height) tiles // The tiles take the the shape of a grid using CSS grid // The tile can represent a part of the snake or an apple // Each tile has a content div that takes an absolute position // The content can fill the tile or slide in or out from any direction to take the shape of a transitioning snake head or tail const grid = document.querySelector(".grid"); for (let i = 0; i < width * height; i++) { const content = document.createElement("div"); content.setAttribute("class", "content"); content.setAttribute("id", i); // Just for debugging, not used const tile = document.createElement("div"); tile.setAttribute("class", "tile"); tile.appendChild(content); grid.appendChild(tile); } const tiles = document.querySelectorAll(".grid .tile .content"); const containerElement = document.querySelector(".container"); const noteElement = document.querySelector("footer"); const contrastElement = document.querySelector(".contrast"); const scoreElement = document.querySelector(".score"); // Initialize layout resetGame(); // Resets game variables and layouts but does not start the game (game starts on keypress) function resetGame() { // Reset positions snakePositions = [171, 170, 169, 168]; applePosition = 100; // Initially the apple is always at the same position to make sure it's reachable // Reset game progress startTimestamp = undefined; lastTimestamp = undefined; stepsTaken = -1; // It's -1 because then the snake will start with a step score = 0; contrast = 1; // Reset inputs inputs = []; // Reset header contrastElement.innerText = `${Math.floor(contrast * 100)}%`; scoreElement.innerText = hardMode ? `H ${score}`: score; // Reset tiles for (const tile of tiles) { resetTileSize(tile); tile.style.backgroundColor = "transparent"; } // Render apple tiles[applePosition].style.backgroundColor = color; tiles[applePosition].style.borderRadius = "50%"; // Render snake for (const i of snakePositions.slice(0, -1)) { const snakePart = tiles[i]; snakePart.style.backgroundColor = color; // Set up transition directions for head and tail if (i == snakePositions[0]) snakePart.style.left = 0; if (i == snakePositions[snakePositions.length - 1]) snakePart.style.right = 0; } } // Handle user inputs (e.g. start the game) window.addEventListener("keydown", function (event) { // If not an arrow key or space or H was pressed then return if ( ![ "ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown", " ", "H", "h", "E", "e"]. includes(event.key)) return; // If an arrow key was pressed then first prevent default event.preventDefault(); // If space was pressed restart the game if (event.key == " ") { resetGame(); startGame(); return; } // Set Hard mode if (event.key == "H" || event.key == "h") { hardMode = true; fadeSpeed = 4000; fadeExponential = 1.025; noteElement.innerHTML = `Hard mode. Press space to start!`; noteElement.style.opacity = 1; resetGame(); return; } // Set Easy mode if (event.key == "E" || event.key == "e") { hardMode = false; fadeSpeed = 5000; fadeExponential = 1.024; noteElement.innerHTML = `Easy mode. Press space to start!`; noteElement.style.opacity = 1; resetGame(); return; } // If an arrow key was pressed add the direction to the next moves // Do not allow to add the same direction twice consecutively // The snake can't do a full turn either // Also start the game if it hasn't started yet if ( event.key == "ArrowLeft" && inputs[inputs.length - 1] != "left" && headDirection() != "right") { inputs.push("left"); if (!gameStarted) startGame(); return; } if ( event.key == "ArrowUp" && inputs[inputs.length - 1] != "up" && headDirection() != "down") { inputs.push("up"); if (!gameStarted) startGame(); return; } if ( event.key == "ArrowRight" && inputs[inputs.length - 1] != "right" && headDirection() != "left") { inputs.push("right"); if (!gameStarted) startGame(); return; } if ( event.key == "ArrowDown" && inputs[inputs.length - 1] != "down" && headDirection() != "up") { inputs.push("down"); if (!gameStarted) startGame(); return; } }); // Start the game function startGame() { gameStarted = true; noteElement.style.opacity = 0; window.requestAnimationFrame(animate); } // The main game loop // This function gets invoked approximately 60 times per second to render the game // It keeps track of the total elapsed time and time elapsed since last call // Based on that animates the snake either by transitioning it in between tiles or stepping it to the next tile function animate(timestamp) { if (startTimestamp === undefined) startTimestamp = timestamp; const totalElapsedTime = timestamp - startTimestamp; const timeElapsedSinceLastCall = timestamp - lastTimestamp; try { const stepsShouldHaveTaken = Math.floor(totalElapsedTime / speed); const percentageOfStep = totalElapsedTime % speed / speed; // If the snake took a step from a tile to another one if (stepsTaken != stepsShouldHaveTaken) { stepAndTransition(percentageOfStep); .........完整代码请登录后点击上方下载按钮下载查看
网友评论0