-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
171 lines (149 loc) · 4.83 KB
/
main.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
'use strict'
// ==== VARIABLES
// start
const startBtn = document.querySelector('.start')
let speed = 500
let modifier = 0.75
let speedId = 0
// score
let score = 0
const scoreboard = document.querySelector('.scoreboard')
// grid
const grid = document.querySelector('.grid')
const width = 20
let squares = []
const gameOver = document.querySelector('.game-over')
// snake
let currentSnake = [185,184,183]
let direction = 1
// apple
let appleIndex = 0
// direction buttons
const btnUp = document.querySelector('.btn-up')
const btnRight = document.querySelector('.btn-right')
const btnDown = document.querySelector('.btn-down')
const btnLeft = document.querySelector('.btn-left')
// copyright
const copyrightYear = document.querySelector('.copyright-year')
// ==== HANDLE
// directions
function directionUp() { direction = -width }
function directionRight() { direction = 1 }
function directionDown() { direction = width }
function directionLeft() { direction = -1 }
function handleSnakeKeyControl(e) {
// change direction on keydown
if (e.keyCode === 38) { // up
directionUp()
} else if (e.keyCode === 39) { // right
directionRight()
} else if (e.keyCode === 40) { // down
directionDown()
} else if (e.keyCode === 37) { // left
directionLeft()
}
}
function handleSnakeBtnControl() {
// change direction on button
btnUp.addEventListener('click', directionUp)
btnRight.addEventListener('click', directionRight)
btnDown.addEventListener('click', directionDown)
btnLeft.addEventListener('click', directionLeft)
}
function handleEatApple(tail) {
// eat and generate apple
squares[currentSnake[0]].classList.remove('apple')
generateApple()
// grow snake
squares[tail].classList.add('snake')
currentSnake.push(tail)
// increase speed
clearInterval(speedId)
speed = speed * modifier
speedId = setInterval(handleSnakeMove, speed)
// update score
score++
scoreboard.textContent = score
}
function handleSnakeMove() {
// stop movement and show 'game over' if snake hits
if (
(currentSnake[0] - width < 0 && direction === -width) || // top
(currentSnake[0] % width === width-1 && direction === 1) || // right
(currentSnake[0] + width >= width*width && direction === width) || // bottom
(currentSnake[0] % width === 0 && direction === -1) || // left
squares[currentSnake[0] + direction].classList.contains('snake') // self
) {
gameOver.classList.remove('game-over-hidden')
return clearInterval(speedId)
}
// snake motion, remove tail add new head
const tail = currentSnake.pop()
squares[tail].classList.remove('snake')
currentSnake.unshift(currentSnake[0] + direction)
squares[currentSnake[0]].classList.add('snake')
// lookout for apple
if (squares[currentSnake[0]].classList.contains('apple')) {
handleEatApple(tail)
}
}
function handleStartGame() {
// clear interval
clearInterval(speedId)
// remove snake + apple + gameOver
gameOver.classList.add('game-over-hidden')
currentSnake.forEach( i => squares[i].classList.remove('snake') )
squares[appleIndex].classList.remove('apple')
// reset values + scoreboard + apple
currentSnake = [185,184,183]
direction = 1
speed = 500
score = 0
scoreboard.textContent = score
generateApple()
// trigger movement
currentSnake.forEach( i => squares[i].classList.add('snake'))
speedId = setInterval(handleSnakeMove, speed)
}
// ==== GENERATE
function generateYear() {
// generate year for copyright sign-off
copyrightYear.textContent = new Date().getFullYear()
}
function generateGrid() {
// generate grid
for (let i = 0; i < width*width; i++) {
// create div and add 'square' class
const square = document.createElement('div')
square.classList.add('square')
grid.appendChild(square)
squares.push(square)
}
}
function generateSnake() {
// add 'snake' class to currentSnake i's within squares
currentSnake.forEach( i => squares[i].classList.add('snake'))
}
function generateApple() {
// add 'apple' class to random square in grid when snake overlaps with current apple
do {
appleIndex = Math.floor(Math.random() * squares.length)
// checks to make sure apples don't generate on snake
let isOnSnake = currentSnake.includes(appleIndex)
if(isOnSnake) {
generateApple()
}
} while (squares[appleIndex].classList.contains('snake'))
squares[appleIndex].classList.add('apple')
}
// ==== WATCH
function watchStart() {
document.addEventListener('keydown', handleSnakeKeyControl)
handleSnakeBtnControl()
startBtn.addEventListener('click', handleStartGame)
}
// ==== ON LOAD
generateYear()
generateGrid()
generateSnake()
watchStart()