|
| 1 | +const canvas = document.getElementById("canvas"); |
| 2 | +const canvasContext = canvas.getContext("2d"); |
| 3 | +const pacmanFrames = document.getElementById("animation"); |
| 4 | +const ghostFrames = document.getElementById("ghosts"); |
| 5 | + |
| 6 | +let createRect = (x, y, width, height, color) => { |
| 7 | + canvasContext.fillStyle = color; |
| 8 | + canvasContext.fillRect(x, y, width, height); |
| 9 | +}; |
| 10 | + |
| 11 | +const DIRECTION_RIGHT = 4; |
| 12 | +const DIRECTION_UP = 3; |
| 13 | +const DIRECTION_LEFT = 2; |
| 14 | +const DIRECTION_BOTTOM = 1; |
| 15 | +let lives = 3; |
| 16 | +let ghostCount = 4; |
| 17 | +let ghostImageLocations = [ |
| 18 | + { x: 0, y: 0 }, |
| 19 | + { x: 176, y: 0 }, |
| 20 | + { x: 0, y: 121 }, |
| 21 | + { x: 176, y: 121 }, |
| 22 | +]; |
| 23 | + |
| 24 | +// Game variables |
| 25 | +let fps = 30; |
| 26 | +let pacman; |
| 27 | +let oneBlockSize = 20; |
| 28 | +let score = 0; |
| 29 | +let ghosts = []; |
| 30 | +let wallSpaceWidth = oneBlockSize / 1.6; |
| 31 | +let wallOffset = (oneBlockSize - wallSpaceWidth) / 2; |
| 32 | +let wallInnerColor = "black"; |
| 33 | + |
| 34 | +// we now create the map of the walls, |
| 35 | +// if 1 wall, if 0 not wall |
| 36 | +// 21 columns // 23 rows |
| 37 | +let map = [ |
| 38 | + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], |
| 39 | + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], |
| 40 | + [1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1], |
| 41 | + [1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1], |
| 42 | + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], |
| 43 | + [1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1], |
| 44 | + [1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1], |
| 45 | + [1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1], |
| 46 | + [0, 0, 0, 0, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 0, 0, 0, 0], |
| 47 | + [1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1], |
| 48 | + [2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2], |
| 49 | + [1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1], |
| 50 | + [0, 0, 0, 0, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 0, 0, 0, 0], |
| 51 | + [0, 0, 0, 0, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 0, 0, 0, 0], |
| 52 | + [1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1], |
| 53 | + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], |
| 54 | + [1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1], |
| 55 | + [1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1], |
| 56 | + [1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1], |
| 57 | + [1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1], |
| 58 | + [1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1], |
| 59 | + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], |
| 60 | + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], |
| 61 | +]; |
| 62 | + |
| 63 | +let randomTargetsForGhosts = [ |
| 64 | + { x: 1 * oneBlockSize, y: 1 * oneBlockSize }, |
| 65 | + { x: 1 * oneBlockSize, y: (map.length - 2) * oneBlockSize }, |
| 66 | + { x: (map[0].length - 2) * oneBlockSize, y: oneBlockSize }, |
| 67 | + { |
| 68 | + x: (map[0].length - 2) * oneBlockSize, |
| 69 | + y: (map.length - 2) * oneBlockSize, |
| 70 | + }, |
| 71 | +]; |
| 72 | + |
| 73 | +// for (let i = 0; i < map.length; i++) { |
| 74 | +// for (let j = 0; j < map[0].length; j++) { |
| 75 | +// map[i][j] = 2; |
| 76 | +// } |
| 77 | +// } |
| 78 | + |
| 79 | +let createNewPacman = () => { |
| 80 | + pacman = new Pacman( |
| 81 | + oneBlockSize, |
| 82 | + oneBlockSize, |
| 83 | + oneBlockSize, |
| 84 | + oneBlockSize, |
| 85 | + oneBlockSize / 5 |
| 86 | + ); |
| 87 | +}; |
| 88 | + |
| 89 | +let gameLoop = () => { |
| 90 | + update(); |
| 91 | + draw(); |
| 92 | +}; |
| 93 | + |
| 94 | +let gameInterval = setInterval(gameLoop, 1000 / fps); |
| 95 | + |
| 96 | +let restartPacmanAndGhosts = () => { |
| 97 | + createNewPacman(); |
| 98 | + createGhosts(); |
| 99 | +}; |
| 100 | + |
| 101 | +let onGhostCollision = () => { |
| 102 | + lives--; |
| 103 | + restartPacmanAndGhosts(); |
| 104 | + if (lives == 0) { |
| 105 | + } |
| 106 | +}; |
| 107 | + |
| 108 | +let update = () => { |
| 109 | + pacman.moveProcess(); |
| 110 | + pacman.eat(); |
| 111 | + updateGhosts(); |
| 112 | + if (pacman.checkGhostCollision(ghosts)) { |
| 113 | + onGhostCollision(); |
| 114 | + } |
| 115 | +}; |
| 116 | + |
| 117 | +let drawFoods = () => { |
| 118 | + for (let i = 0; i < map.length; i++) { |
| 119 | + for (let j = 0; j < map[0].length; j++) { |
| 120 | + if (map[i][j] == 2) { |
| 121 | + createRect( |
| 122 | + j * oneBlockSize + oneBlockSize / 3, |
| 123 | + i * oneBlockSize + oneBlockSize / 3, |
| 124 | + oneBlockSize / 3, |
| 125 | + oneBlockSize / 3, |
| 126 | + "#FEB897" |
| 127 | + ); |
| 128 | + } |
| 129 | + } |
| 130 | + } |
| 131 | +}; |
| 132 | + |
| 133 | +let drawRemainingLives = () => { |
| 134 | + canvasContext.font = "20px Emulogic"; |
| 135 | + canvasContext.fillStyle = "white"; |
| 136 | + canvasContext.fillText("Lives: ", 220, oneBlockSize * (map.length + 1)); |
| 137 | + |
| 138 | + for (let i = 0; i < lives; i++) { |
| 139 | + canvasContext.drawImage( |
| 140 | + pacmanFrames, |
| 141 | + 2 * oneBlockSize, |
| 142 | + 0, |
| 143 | + oneBlockSize, |
| 144 | + oneBlockSize, |
| 145 | + 350 + i * oneBlockSize, |
| 146 | + oneBlockSize * map.length + 2, |
| 147 | + oneBlockSize, |
| 148 | + oneBlockSize |
| 149 | + ); |
| 150 | + } |
| 151 | +}; |
| 152 | + |
| 153 | +let drawScore = () => { |
| 154 | + canvasContext.font = "20px Emulogic"; |
| 155 | + canvasContext.fillStyle = "white"; |
| 156 | + canvasContext.fillText( |
| 157 | + "Score: " + score, |
| 158 | + 0, |
| 159 | + oneBlockSize * (map.length + 1) |
| 160 | + ); |
| 161 | +}; |
| 162 | + |
| 163 | +let draw = () => { |
| 164 | + canvasContext.clearRect(0, 0, canvas.width, canvas.height); |
| 165 | + createRect(0, 0, canvas.width, canvas.height, "black"); |
| 166 | + drawWalls(); |
| 167 | + drawFoods(); |
| 168 | + drawGhosts(); |
| 169 | + pacman.draw(); |
| 170 | + drawScore(); |
| 171 | + drawRemainingLives(); |
| 172 | +}; |
| 173 | + |
| 174 | +let drawWalls = () => { |
| 175 | + for (let i = 0; i < map.length; i++) { |
| 176 | + for (let j = 0; j < map[0].length; j++) { |
| 177 | + if (map[i][j] == 1) { |
| 178 | + createRect( |
| 179 | + j * oneBlockSize, |
| 180 | + i * oneBlockSize, |
| 181 | + oneBlockSize, |
| 182 | + oneBlockSize, |
| 183 | + "#342DCA" |
| 184 | + ); |
| 185 | + if (j > 0 && map[i][j - 1] == 1) { |
| 186 | + createRect( |
| 187 | + j * oneBlockSize, |
| 188 | + i * oneBlockSize + wallOffset, |
| 189 | + wallSpaceWidth + wallOffset, |
| 190 | + wallSpaceWidth, |
| 191 | + wallInnerColor |
| 192 | + ); |
| 193 | + } |
| 194 | + |
| 195 | + if (j < map[0].length - 1 && map[i][j + 1] == 1) { |
| 196 | + createRect( |
| 197 | + j * oneBlockSize + wallOffset, |
| 198 | + i * oneBlockSize + wallOffset, |
| 199 | + wallSpaceWidth + wallOffset, |
| 200 | + wallSpaceWidth, |
| 201 | + wallInnerColor |
| 202 | + ); |
| 203 | + } |
| 204 | + |
| 205 | + if (i < map.length - 1 && map[i + 1][j] == 1) { |
| 206 | + createRect( |
| 207 | + j * oneBlockSize + wallOffset, |
| 208 | + i * oneBlockSize + wallOffset, |
| 209 | + wallSpaceWidth, |
| 210 | + wallSpaceWidth + wallOffset, |
| 211 | + wallInnerColor |
| 212 | + ); |
| 213 | + } |
| 214 | + |
| 215 | + if (i > 0 && map[i - 1][j] == 1) { |
| 216 | + createRect( |
| 217 | + j * oneBlockSize + wallOffset, |
| 218 | + i * oneBlockSize, |
| 219 | + wallSpaceWidth, |
| 220 | + wallSpaceWidth + wallOffset, |
| 221 | + wallInnerColor |
| 222 | + ); |
| 223 | + } |
| 224 | + } |
| 225 | + } |
| 226 | + } |
| 227 | +}; |
| 228 | + |
| 229 | +let createGhosts = () => { |
| 230 | + ghosts = []; |
| 231 | + for (let i = 0; i < ghostCount; i++) { |
| 232 | + let newGhost = new Ghost( |
| 233 | + 9 * oneBlockSize + (i % 2 == 0 ? 0 : 1) * oneBlockSize, |
| 234 | + 10 * oneBlockSize + (i % 2 == 0 ? 0 : 1) * oneBlockSize, |
| 235 | + oneBlockSize, |
| 236 | + oneBlockSize, |
| 237 | + pacman.speed / 2, |
| 238 | + ghostImageLocations[i % 4].x, |
| 239 | + ghostImageLocations[i % 4].y, |
| 240 | + 124, |
| 241 | + 116, |
| 242 | + 6 + i |
| 243 | + ); |
| 244 | + ghosts.push(newGhost); |
| 245 | + } |
| 246 | +}; |
| 247 | + |
| 248 | +createNewPacman(); |
| 249 | +createGhosts(); |
| 250 | +gameLoop(); |
| 251 | + |
| 252 | +window.addEventListener("keydown", (event) => { |
| 253 | + let k = event.keyCode; |
| 254 | + setTimeout(() => { |
| 255 | + if (k == 37 || k == 65) { |
| 256 | + // left arrow or a |
| 257 | + pacman.nextDirection = DIRECTION_LEFT; |
| 258 | + } else if (k == 38 || k == 87) { |
| 259 | + // up arrow or w |
| 260 | + pacman.nextDirection = DIRECTION_UP; |
| 261 | + } else if (k == 39 || k == 68) { |
| 262 | + // right arrow or d |
| 263 | + pacman.nextDirection = DIRECTION_RIGHT; |
| 264 | + } else if (k == 40 || k == 83) { |
| 265 | + // bottom arrow or s |
| 266 | + pacman.nextDirection = DIRECTION_BOTTOM; |
| 267 | + } |
| 268 | + }, 1); |
| 269 | +}); |
0 commit comments