- firtstly ceate new folder and on it add new file name index.html
- and write ! to build html template, and set the title
- to run it we will use live server, we can install it on exstension
- start it with Go Live buttton
- lets now make new file name style.css and script.js
- link the style.css and also script the script.js on head tag
- and add defer atribute on script tag, so it will run after all html load
- then inside body tag, add div, and div with class scores
- in that div add h1 with id score and text 000
- add more h1 with id highScore and text 000
- that below scores div add new div with class game-border-1
- and inside game-border-1 div wrap new div with class game-border-2
- then wrap more div with class game-border-3
- and add more div with id game-board
- below of game-border-1 div, create h1 tag with id instruction-text and text Press spacebar to start the game
- and under that add img with alt snake-logo and download snake logo to use it as src of image
- the src will like snake-game-ai-gen.png
- for next develop we need to comment the h1 and img tag below
- so our code will like this:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake Game</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<div>
<div class="scores">
<h1 id="score">00</h1>
<h1 id="highScore">00</h1>
</div>
<div class="game-border-1">
<div class="game-border-2">
<div class="game-border-3">
<div id="game-board">
</div>
</div>
</div>
</div>
<h1 id="instruction-text">Press spacebar to start the game</h1>
<img src="snake-game-ai-gen.png" alt="snake logo">
</div>
</body>
</html>
- lets start on style.css file, and open unspect mode
- so create body selector then make it display flex, align item of center, justify content also center, height 100vh, margin of 0
- we will add font family of google font with VT323, and use regular 400, and copy the link, copy it on head tag, and then we can copy and use the css rule of vt323
- next we will target the body, .snake. on it add background color of dark gray
- then target the #game-board with border radius 100px, display of grid, and grid template columns of repeat(20, 20px), for grid tempalte row also use repeat(20, 20px), also use margin of 5px
- then we target .game-border-1 with border of some green solid 10px, border radius of 30px, as well box shadow of inset 0 0 0 10px and some green,
- and copy all .game-border-1, use it on .game-border-2 and .game-border-3 , just change the border color and box shadow color, also less the border radius to 26px, 20px
- for game border 2 use 8px of boder and for game borde 3 use 30px for border and 5px for box shadow
- now for #instruction-text, add position of absolute, top of 60%, color of gray, width of 300px, text align with center, text transform to capialize, padding of 30px, and margin of 0
- now target .scores, add display of flex, justify content to space-between
- then target the #score, add color of some green
- and target both of #score, #highScore with font size of 40px, font weight of bolder, and margin of 10px 0
- now target only #highScore, with color some with green, display of none
- then we target .game-border-3, #logo. add color somw brown
- next target #snake, with border some gray 1px dotted
- now target .food with backgroudn color with white, and border gray 5px solid
- we need to add id of logo on img tag, then target it #logo then add position of absolute
- so we will get this following css:
body {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
font-family: 'VT323', monospace;
}
body,
.snake {
background-color: #414141;
}
#game-board {
border-radius: 100px;
display: grid;
grid-template-columns: repeat(20, 20px);
grid-template-rows: repeat(20, 20px);
margin: 5px;
}
.game-border-1 {
border: #595f43 solid 10px;
border-radius: 30px;
box-shadow: inset 0 0 0 10px #595f43;
}
.game-border-2 {
border: #abb78a solid 8px;
border-radius: 26px;
box-shadow: inset 0 0 0 10px #abb78a;
}
.game-border-3 {
border: #8b966c solid 30px;
border-radius: 20px;
box-shadow: inset 0 0 0 5px #8b966c;
}
#instruction-text {
position: absolute;
top: 65%;
color: #333;
width: 300px;
text-align: center;
text-transform: capitalize;
padding: 30px;
margin: 0;
}
.scores {
display: flex;
justify-content: space-between;
}
#score {
color: #abb78a;
}
#score,
#highScore {
font-size: 40px;
font-weight: bolder;
margin: 10px 0;
}
#highScore {
color: #d8ddca;
display: none;
}
.game-border-3,
#logo {
background-color: #c4cfa3;
}
.snake {
border: #5a5a5a 1px dotted;
}
.food {
background-color: #dedede;
border: #999 5px solid;
}
#logo {
position: absolute;
}
- start with open script.js, first we need to define HTML element
- define const variable name board with dom get element id of game-board
- and we create a function name draw, to draw game map, snake, and food
- on draw function, we give board a innerHTML with empty string, to reset the board
- then we call another function name drawSnake
- so we can define drawSnake function, we draw our snake with array and object
- also we need define some game variable
- with a let variable name snake, with value array and object on it, with key x and y also value 10 of each key
- back to drawSnake function, we take snake variable and do forEach, and for segment we do define a const variable name snakeElement with value createGameElement function, that pass div and snake. we give a div with snake class
- so we define some function to create snake and food div
- firstly we create new function name createGameElement with parameter tag and className
- on that function define new const variabel name element with value dom create element and passing tag as argument
- then we use element use className with value className
- then we need to return the element
- back to drawSnake function, add setPostition function with argument snakeElement and segment
- and we define some function to set the position of snake or food
- create new function name setPosition that take parameter element and position
- we take element.style.gridColumn with value position.x
- also we need add element.style.gridRow with value position.y
- now back to drawSnake function, below setPosition, add board.appendChild passing snakeElement
- next we define new function name drawFood. inside it we create const variable name foodElement with value createGameElement that passing argument div and food
- below that add setPosition function that pass foodElement and food argument
- back to define game variable, below of variable sneake
- create let variable name food with value generateFood
- then create generateFood function
- back to drawFood, we need to add board.appendChild passing the foodElement
- move on to generateFood function, create new const variable called x, with value Math.random() * 20,
- back to game variable, define const variable name gridSize with value 20, and change the x on generateFood function to Math.floor(Math.random() * gridSize) + 1
- and also add y with value same as x, and return { x, y }
- back to drawFunction, add drawFood below drawSnake
- next we gonna make the snake move, so create function called move
- and create const variable name head with value { ...sneake[0] }
- and we create conditional with switch below that
- use direction on switch, before that back to game variable and devine a let variable name direction with value right
- inside of switch case, we gonna make some case
- if case right, add head.x++
- for up, head.y--
- if down, head.y++
- and if left, head.x--
- then below of switch, add snake.unshift(head)
- after that we also take snake.pop
- then we make the snake become bigger when hit the food
- so we dont need to do pop, when the snake head coodinate is same as food coordinate
- so we make if conditional, where if head.x === food.x && head.y === food.y, so we change food with value generateFood
- below of food, add clearInterval(), to clear past interval
- then add gameInterval, but we need to define new let variable on game variable called gameInterval with no value
- so back to gameInterval, set it with setInterval with call back function with move(), checkCollision() and draw()
- also give interval with variable name gameSpeedDelay. also define gameSpeedDelay variable on game variable with const and value 200
- than create else statement, that will do snake.pop()
- so we now create start game function
- create new function name startGame, and alos create game variable let name gameStarted with value false
- back to startGame function, we set gameStarted to true
- then we need to define HTML element name instructionText with value dom get element by id instruction-text
- also define logo with value dom get element by id logo
- now back to startGame function, and add instructionText.style.display = "none”
- same with logo add logo.style.display = “none"
- then we set gameInterval with value setInterval and a callback function with move(), checkCollision() then draw()
- and pass gameSpeedDelay as interval
- now we will define keypress event listener
- create new fucntion name handleKeyPress with parameter event
- create conditional if, that if (!gameStarted && event.code === "Space") || (!gameStarted && event.code === " "), we gonna startGame()
- and add else statement with switch case of event.key
- if case is ArrowUp ww change direction to up, and break
- and for case ArrowDown change to down
- for case ArrowLeft change to left
- and also case ArrowRight change to right
- and below of handleKeyPress, add dom addEventListener of keydown, with callback function of handleKeyPress
- but there is a bug, when we eat food, the snake will move faster
- on every gameInterval set, add checkCollision() after move() too
- back to move function, on if statement, below food call increateSpeed() function
- under of addEventListener, add increaseSpeed function, create if statement, that gameSpeedSelay > 150 and decrease game delay by 5, gameSpeedDelay -= 5
- on clearInterval pass gameSpeedDelay
- back to increaseSpeed function, add else if statement where gameSpeedDelay > 100, do gameSpeedDelay -= 3
- then add more else if for > 50 and >25, with -= 2 and -= 1
- now we gonna make collision
- create checkCollision function, and add const variable with value snake[0]
- then create if statement that head.x < 1 || head.x > gridSize || head.y < 1 || head.y > gridSize. that for the wall collision. and do resetGame() function
- also if snake hit snake it self
- create for loop that let i = 1; i < snake.length; i++
- so add if statement, that head.x === snake[i].x && head.y === snake[i].y, and also do resetGame() function
- then we create resetGame function, that call snake with value [{ x: 10, y: 10}]
- and call food with value generateFood
- and also direction with value rigth
- also gameSpeedDelay of 200
- next create updateScore function, create const variable name currentScore with value snake.lenght - 1
- back to define HTML element, add const variable name score with value dom get element by id score
- and back to updateScore, add score.textContent with value currentScore.toString().padString(3, "0")
- and back to draw function, and call updateScore() function
- also for highScore, on resetGame function, on top of snake call updateHighScore() and stopGame() function
- so first lets create stopGame function, and clearInterval(gameInterval)
- then set the gameStarted = false,
- and instructionText.style.display = "block" also same to logo.style.display = "block"
- next create updateHighScore function, call new const variable name currentScore with value snake.length - 1
- then add if statement that currentScore > highScore, do highScore = currentScore
- because we dont have highScore, lets define it on HTML element
- create const variable name highScoreText with value dom get element by id highScore
- we also need to define highScore on game variable, with let variable and value of 0
- back to updateHighScore function, on if statement, add highScoreText.textContent = highScore.toString().padstart(3, "0")
- we need to unhide the highScoreText.style.display = "block"
- because when the game done, the sometime the food still generated on start
- to fixed it back to drawFood function, wrap the exist code with if statement when gameStarted is truthy
- and the game is done