In this one video we will make an entire game and you’ll actually understand it through diagrams and more. We’ll create Pong using JavaScript and you’ll learn about Receiving User Input, Handling Collisions, Moving AI, Creating User Interfaces, Playing Sound and Much more. You can play the game here. The sound file is here.
All of the heavily commented code follows below. If you want me to make a specific game please tell me.
If you enjoy free tutorials like this consider donating $1 on Patreon. Starting next month, I will be uploading additional content every month only for the Patreons that help me keep my channel alive and free.
Code From the Video
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 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
// Reference to the canvas element let canvas; // Context provides functions used for drawing and // working with Canvas let ctx; // Used to monitor whether paddles and ball are // moving and in what direction let DIRECTION = { STOPPED: 0, UP: 1, DOWN: 2, LEFT: 3, RIGHT: 4 }; // The paddle object used for both the player and AI class Paddle{ constructor(side) { // Define size of paddle this.width = 15; this.height = 65; // Put paddle on right or left for player and AI this.x = side === 'left' ? 150 : canvas.width - 150; // Center the paddle this.y = canvas.height / 2; // Will hold the increasing score this.score = 0; // Defines movement direction of paddles this.move = DIRECTION.STOPPED; // Defines how quickly paddles can be moved this.speed = 11; } } // The ball object class Ball{ constructor(newSpeed) { // Size of ball this.width = 15; this.height = 15; // Position in center this.x = canvas.width / 2; this.y = canvas.height / 2; // Ball moves in x & y direction so monitor both this.moveX = DIRECTION.STOPPED; this.moveY = DIRECTION.STOPPED; // Speed ball can move this.speed = newSpeed; } } let player; let aiPlayer; let ball; // Monitors whether ball is currently in play let running = false; let gameOver = false; // Will be used to add a delay before play resumes let delayAmount; // Should ball target player or AI let targetForBall; // Used to play sounds when paddle hits a ball let beepSound; // Call for our function to execute when page is loaded document.addEventListener('DOMContentLoaded', SetupCanvas); function SetupCanvas(){ // Get reference to canvas element canvas = document.getElementById('my-canvas'); // Get methods for manipulating the canvas ctx = canvas.getContext('2d'); // Define canvas size canvas.width = 1400; canvas.height = 1000; // Create player and AI paddles player = new Paddle('left'); aiPlayer = new Paddle('right'); // Create ball and define its speed ball = new Ball(7); // Make AI paddle slightly slower then the ball // and the player aiPlayer.speed = 6.5; // Set target for ball to the player targetForBall = player; // Set delay between scores delayAmount = (new Date()).getTime(); // Allow for playing sound beepSound = document.getElementById('beepSound'); beepSound.src = 'beep.wav'; // Handle keyboard input document.addEventListener('keydown', MovePlayerPaddle); document.addEventListener('keyup', StopPlayerPaddle); // Draw the board for the 1st time Draw(); } function Draw(){ // Clear the canvas ctx.clearRect(0,0,canvas.width,canvas.height); // Draw Canvas background ctx.fillStyle = 'black'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw Paddles ctx.fillStyle = 'white'; ctx.fillRect(player.x, player.y, player.width, player.height); ctx.fillRect(aiPlayer.x, aiPlayer.y, aiPlayer.width, aiPlayer.height); // Draw Ball ctx.fillRect(ball.x, ball.y, ball.width, ball.height); // Set font for scores ctx.font = '80px Arial'; ctx.textAlign = 'center'; // Draw scores ctx.fillText(player.score.toString(), (canvas.width/2) - 300, 100); ctx.fillText(aiPlayer.score.toString(), (canvas.width/2) + 300, 100); // Declare a winner if(player.score === 2){ ctx.fillText("Player Wins", canvas.width/2, 300); gameOver = true; } if(aiPlayer.score === 2){ ctx.fillText("AI Wins", canvas.width/2, 300); gameOver = true; } } // All the logic is here including collision detection, // player / AI paddle movement, keeping assets on the board function Update(){ if(!gameOver){ // Handle if ball scores on the player if(ball.x <= 0){ ResetBall(aiPlayer, player); } // Handle if ball scores on AI if(ball.x >= canvas.width - ball.width){ ResetBall(player, aiPlayer); } // Handle if ball hits the top or bottom if(ball.y <= 0){ ball.moveY = DIRECTION.DOWN; } if(ball.y >= canvas.height - ball.height){ ball.moveY = DIRECTION.UP; } // Move player paddle if they are pressing down // buttons if(player.move === DIRECTION.DOWN){ player.y += player.speed; } else if(player.move === DIRECTION.UP){ player.y -= player.speed; } // If player tries to move off the board prevent that if(player.y < 0){ player.y = 0; } else if(player.y >= (canvas.height - player.height)){ player.y = canvas.height - player.height; } // Add a delay and only if a current target is set move // the ball if(AddADelay() && targetForBall){ // Move ball toward he target ball.moveX = targetForBall === player ? DIRECTION.LEFT : DIRECTION.RIGHT; // Move either up or down to randomize ball movement ball.moveY = [DIRECTION.UP, DIRECTION.DOWN][Math.round(Math.random())]; // Start ball from the middle ball.y = canvas.height / 2; // Nullify target because target changes repeatedly // as the ball bounces targetForBall = null; } // Move ball based on moveY & moveX values if (ball.moveY === DIRECTION.UP){ ball.y -= ball.speed; } else if (ball.moveY === DIRECTION.DOWN){ ball.y += ball.speed; } if (ball.moveX === DIRECTION.LEFT){ ball.x -= ball.speed; } else if (ball.moveX === DIRECTION.RIGHT){ ball.x += ball.speed; } // Handle AI up & down movement if (aiPlayer.y > ball.y - (aiPlayer.height / 2)) { if (ball.moveX === DIRECTION.RIGHT){ aiPlayer.y -= aiPlayer.speed; } else { aiPlayer.y -= aiPlayer.speed; } } if (aiPlayer.y < ball.y - (aiPlayer.height / 2)) { if (ball.moveX === DIRECTION.RIGHT){ aiPlayer.y += aiPlayer.speed; } else { aiPlayer.y += aiPlayer.speed; } } // If AI tries to move off the board handle that if(aiPlayer.y < 0){ aiPlayer.y = 0; } else if(aiPlayer.y >= (canvas.height - aiPlayer.height)){ aiPlayer.y = canvas.height - aiPlayer.height; } // Handle ball collision with the players paddle // x represents the upper left hand position of // the object. So we have to subtract the ball width // to check if the balls x is <= paddle x. // The same must be true for the player x to have // a collision if (ball.x - ball.width <= player.x && ball.x >= player.x - player.width) { // If also this is true for y in the upper left // hand corner we have a collison if (ball.y <= player.y + player.height && ball.y + ball.height >= player.y) { ball.x = (player.x + ball.width); // Move ball toward right of screen ball.moveX = DIRECTION.RIGHT; beepSound.play(); } } // Handle ball collison with AI paddle if (ball.x - ball.width <= aiPlayer.x && ball.x >= aiPlayer.x - aiPlayer.width) { if (ball.y <= aiPlayer.y + aiPlayer.height && ball.y + ball.height >= aiPlayer.y) { ball.x = (aiPlayer.x - ball.width); ball.moveX = DIRECTION.LEFT; beepSound.play(); } } } } // If we are not in play mode start the game running and loop // through updates and draws till the end of the game function MovePlayerPaddle(key){ if(running === false){ running = true; window.requestAnimationFrame(GameLoop); } // Handle up arrow and w input if(key.keyCode === 38 || key.keyCode === 87) player.move = DIRECTION.UP; // Handle down arrow and s input if(key.keyCode === 40 || key.keyCode === 83) player.move = DIRECTION.DOWN; } function StopPlayerPaddle(evt){ player.move = DIRECTION.STOPPED; } // Loops constantly updating position of assets // while drawing them function GameLoop(){ Update(); Draw(); // Keep looping if(!gameOver) requestAnimationFrame(GameLoop); } function ResetBall(whoScored, whoLost){ // Increment the player that scored whoScored.score++; // Reset the ball and increase speed let newBallSpeed = ball.speed + .2; ball = new Ball(newBallSpeed); // Set new target for the ball targetForBall = whoLost; // Reset the the delay start time delayAmount = (new Date()).getTime(); } // Used to add a second delay after scoring function AddADelay(){ return ((new Date()).getTime() - delayAmount >= 1000); } JSTut10.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <!-- Set the page width to the device width --> <meta name="viewport" content="width = device-width, initial-scale = 1"> <title>JavaScript Pong</title> <link rel="stylesheet" type="text/css" href="mainstyle.css"> <script src="pong.js"></script> </head> <body> <!-- What we will be drawing our game on --> <canvas id='my-canvas'></canvas> <!-- Embedded beep sound in the web page which I'll target in the JS --> <audio id="beepSound" style="display: none;"></audio> </body> </html> mainstyle.css body { text-align: center; background: #fff; } /* # is used to target ids in HTML */ #my-canvas { background: #fff; margin-left: 10px; margin-top: 10px; } |
Leave a Reply