-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
238 lines (212 loc) · 7.01 KB
/
app.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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// event listener that runs after entire HTML has loaded
document.addEventListener('DOMContentLoaded', () => {
// allowing js to access our grid
const grid = document.querySelector('.grid')
// access all 200 divs bruh >.<
// Array.from() allows each grid to have an expecific index
let squares = Array.from(document.querySelectorAll('.grid div'))
// acces span to display score
const scoreDisplay = document.getElementById('score')
// button functionality
const startButton = document.getElementById('startButton')
// telling js the size of our grid
const width = 10
// create timmer
let timerId
let score = 0
let nextRandom = 0
//Tetrominoes
//each array index represents a part of the tetromino shape
const lTetromino = [
[1, width+1, width*2+1, 2],
[width, width+1, width+2, width*2+2],
[1, width+1, width*2+1, width*2],
[width, width*2, width*2+1, width*2+2]
]
const zTetromino = [
[0, width, width+1, width*2+1],
[width+1, width+2, width*2, width*2+1],
[0, width, width+1, width*2+1],
[width+1, width+2, width*2, width*2+1]
]
const tTetromino = [
[1, width, width+1, width+2],
[1, width+1, width+2, width*2+1],
[width, width+1, width+2, width*2+1],
[1, width, width+1, width*2+1]
]
const oTetromino = [
[0, 1, width, width+1],
[0, 1, width, width+1],
[0, 1, width, width+1],
[0, 1, width, width+1]
]
const iTetromino = [
[1, width+1, width*2+1, width*3+1],
[width, width+1, width+2, width+3],
[1, width+1, width*2+1, width*3+1],
[width, width+1, width+2, width+3]
]
const tetrominoes = [lTetromino, zTetromino, tTetromino, oTetromino, iTetromino]
// console.log(tetrominoes)
let currentPosition = 4
// passes every first rotation of every random tetromino
let currentRotation = 0
// randomly select tetromino and rotation
let random = Math.floor(Math.random()*tetrominoes.length)
// console.log(random)
let current = tetrominoes[random][currentRotation]
// console.log(current)
// draw tetromino
function draw() {
current.forEach(index => {
squares[currentPosition + index].classList.add('tetromino')
})
}
// see shape on grid
// draw()
//undraw tetromino
function undraw(){
current.forEach(index => {
squares[currentPosition + index].classList.remove('tetromino')
})
}
//make tetromino go down grid
// timerId = setInterval(moveDown, 1000)
//eventListeners for keyCodes
function control(event) {
if(event.keyCode === 37) {
moveLeft()
} else if (event.keyCode === 38) {
rotate()
} else if (event.keyCode === 39) {
moveRight()
} else if (event.keyCode === 40) {
moveDown()
}
}
document.addEventListener('keyup', control)
//move down function
function moveDown() {
undraw()
currentPosition += width
draw()
freeze()
}
//stop shape and counter from keep going off the grid using '.some' (if at least 1 statement is true some will run)
function freeze() {
if(current.some(index => squares[currentPosition + index + width].classList.contains('taken'))) {
current.forEach(index => squares[currentPosition + index].classList.add('taken'))
// have a new tetromino fall
//passing nextRandom value into the random value
random = nextRandom
nextRandom = Math.floor(Math.random() * tetrominoes.length)
current = tetrominoes[random][currentRotation]
currentPosition = 4
draw()
displayShape()
addScore()
gameOver()
}
}
//move tetrominoes left
//stop tetrominoes once they're at the edge
function moveLeft() {
undraw()
const isAtLeftEdge = current.some(index => (currentPosition + index) % width === 0)
if(!isAtLeftEdge) currentPosition -=1
// if some of the squares go into the left space that has a div of class 'taken' push it back one space
if(current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
currentPosition +=1
}
draw()
}
// move tetrominoes right
//stop tetrominoes once they're at the edge
function moveRight() {
undraw()
const isAtRightEdge = current.some(index => (currentPosition + index) % width === width -1)
if(!isAtRightEdge) currentPosition +=1
// if some of the squares go into the right space that has a div of class 'taken' push it back one space
if(current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
currentPosition -=1
}
draw()
}
//rotate tetromino by assigning to a key
function rotate() {
undraw()
currentRotation ++
// if index = 4 (current amount of shapes) go back to the first rotation
if(currentRotation === current.length) {
currentRotation = 0
}
current = tetrominoes[random][currentRotation]
draw()
}
//show incoming shape
const displaySquares = document.querySelectorAll('.miniGrid div')
const displayWidth = 4
let displayIndex = 0
//array of tetraminoes in their first rotation
//we'll only be displaying what shape is coming up next to the user, not it's exact location
const upNextTetrominoes = [
[1, displayWidth+1, displayWidth*2+1, 2], //lTetromino
[0, displayWidth, displayWidth+1, displayWidth*2+1], //zTetromino
[1, displayWidth, displayWidth+1, displayWidth+2],//tTetromino
[0, 1, displayWidth, displayWidth+1], //oTetromino
[1, displayWidth+1, displayWidth*2+1, displayWidth*3+1] //iTetromino
]
function displayShape() {
//remove trace of tetromino on miniGrid
displaySquares.forEach(square => {
square.classList.remove('tetromino')
})
upNextTetrominoes[nextRandom].forEach(index => {
displaySquares[displayIndex + index].classList.add('tetromino')
})
}
// start and pause functionality
startButton.addEventListener('click', () => {
// console.log('butts')
if (timerId) {
clearInterval(timerId)
timerId = null
} else {
draw()
timerId = setInterval(moveDown, 1000)
nextRandom = Math.floor(Math.random()*tetrominoes.length)
displayShape()
}
})
//add score
function addScore() {
for (let i=0; i < 199; i +=width) {
const row = [i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9]
if(row.every(index => squares[index].classList.contains('taken'))) {
score +=10
scoreDisplay.innerHTML = score
row.forEach(index => {
squares[index].classList.remove('taken')
squares[index].classList.remove('tetromino')
})
//rome all the divs that have been filled in the first buttom row
const squaresRemoved = squares.splice(i, width)
// console.log(squaresRemoved)
squares = squaresRemoved.concat(squares)
squares.forEach(cell => grid.appendChild(cell))
}
}
}
//!!gameOver!!
function gameOver() {
if(current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
scoreDisplay.innerHTML = 'Game Over'
clearInterval(timerId)
// game clears and reloads but `Game Over` message disappears too fast
window.location.reload()
}
}
// console.log(squares)
})
// console.log('butts')