How to Create Pong Game in JavaScript?

A Pong game is a two-player paddle game where each player's task is to save the ball from hitting the wall. Whenever player 1 hits the ball at the opponent's wall then player one will receive a point, and similarly, player 2 will get a point if he/she hits the ball at the opponent's wall. In this tutorial, we will create a Pong Game in JavaScript using HTML5 Canvas.

Game Controls

Before implementing the game, let's understand the controls:

  • Left Player: Use 'Z' key to move up and 'S' key to move down

  • Right Player: Use arrow keys (? up arrow and ? down arrow) to move up and down

Key Functions

The game uses several JavaScript functions to handle different aspects:

  • DownHandler() & UpHandler() ? Handle keypress events for paddle movement

  • Ball() ? Draws the game ball on the canvas

  • Scores() ? Displays the current scores for both players

  • collisionsWithLeftPaddle() & collisionsWithRightPaddle() ? Handle ball-paddle collision detection

  • computeCollisionsWithWallsAndPaddle() ? Manages all collision detection

  • drawLeftPaddle() & drawRightPaddle() ? Draw the player paddles

  • Scene() ? Creates the game field with center line

  • draw() ? Main game loop that renders everything

Complete Pong Game Implementation

Here's the complete implementation of the Pong game using HTML5 Canvas and JavaScript:

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8" />
   <title>Tutorials Point Pong Game</title>
   <style>
      canvas {
         background: yellow;
         display: block;
         margin: auto;
         border: 2px solid black;
      }
      body {
         text-align: center;
         font-family: Arial, sans-serif;
      }
      .controls {
         margin: 10px 0;
         font-size: 14px;
      }
   </style>
</head>
<body>
   <h1>Pong Game</h1>
   <div class="controls">
      Left Player: Z (Up) / S (Down) | Right Player: ? (Up) / ? (Down)
   </div>
   <canvas id="board" width="650" height="350"></canvas>
   <script>
      var canvas = document.getElementById("board");
      var ctx = canvas.getContext("2d");
      var x = canvas.width/2;
      var y = canvas.height-30;
      var dx = 4;
      var dy = -4;
      var ballRadius = 10;

      // Variables to handle paddle movement
      var leftUpPressed = false;
      var leftDownPressed = false;
      var rightUpPressed = false;
      var rightDownPressed = false;

      function DownHandler(e) {
         if(e.keyCode == 90) { // Z key
            leftUpPressed = true;
         }
         else if (e.keyCode == 83) { // S key
            leftDownPressed = true;
         }
         if (e.keyCode == 38) { // Up arrow
            rightUpPressed = true;
         }
         else if (e.keyCode == 40) { // Down arrow
            rightDownPressed = true;
         }
      }
      
      function UpHandler(e) {
         if (e.keyCode == 90) { // Z key
            leftUpPressed = false;
         }
         else if (e.keyCode == 83) { // S key
            leftDownPressed = false;
         }
         if (e.keyCode == 38) { // Up arrow
            rightUpPressed = false;
         }
         else if (e.keyCode == 40) { // Down arrow
            rightDownPressed = false;
         }
      }

      function Ball() {
         ctx.beginPath();
         ctx.arc(x, y, ballRadius, 0, Math.PI*2);
         ctx.fillStyle = "red";
         ctx.fill();
         ctx.closePath();
      }

      var leftScore = 0;
      var rightScore = 0;

      function Scores() {
         ctx.font = "80px Arial";
         ctx.fillStyle = "blue";
         ctx.fillText(leftScore, (canvas.width / 2) - 80, 70);
         ctx.fillText(rightScore, (canvas.width / 2) + 40, 70);
      }

      function collisionsWithLeftPaddle() {
         if ((x - ballRadius) <= 5 + l_PaddleWidth) {
            if (y > l_PaddleY && y < l_PaddleY + l_PaddleHeight)
               dx = -dx;
            else if ((x - ballRadius) <= 0) {
               rightScore++;
               // Reset ball position
               x = canvas.width / 2;
               y = canvas.height / 2;
               dx = -dx;
               dy = -dy;
            }
         }
      }

      function collisionsWithRightPaddle() {
         if ((x + ballRadius) >= canvas.width - (r_PaddleWidth + 5)) {
            if (y > r_PaddleY && y < r_PaddleY + r_PaddleHeight)
               dx = -dx;
            else if (x + ballRadius >= canvas.width) {
               leftScore++;
               // Reset ball position
               x = canvas.width / 2;
               y = canvas.height / 2;
               dx = -dx;
               dy = -dy;
            }
         }
      }

      function computeCollisionsWithWallsAndPaddle() {
         collisionsWithLeftPaddle();
         collisionsWithRightPaddle();
         if (((y - ballRadius) <= 0) || ((y + ballRadius) >= canvas.height)) {
            dy = -dy;
         }
      }

      // Left paddle properties
      var l_PaddleHeight = 80;
      var l_PaddleWidth = 10;
      var l_PaddleX = 5;
      var l_PaddleY = canvas.height / 2 - l_PaddleHeight / 2;
      
      function drawLeftPaddle() {
         ctx.beginPath();
         ctx.rect(l_PaddleX, l_PaddleY, l_PaddleWidth, l_PaddleHeight);
         ctx.fillStyle = "green";
         ctx.fill();
         ctx.closePath();
         if (leftDownPressed && l_PaddleY < canvas.height - l_PaddleHeight) {
            l_PaddleY += 7;
         }
         else if (leftUpPressed && l_PaddleY > 0) {
            l_PaddleY -= 7;
         }
      }

      // Right paddle properties
      var r_PaddleHeight = 80;
      var r_PaddleWidth = 10;
      var r_PaddleX = canvas.width - (r_PaddleWidth + 5);
      var r_PaddleY = canvas.height / 2 - r_PaddleHeight / 2;
      
      function drawRightPaddle() {
         ctx.beginPath();
         ctx.rect(r_PaddleX, r_PaddleY, r_PaddleWidth, r_PaddleHeight);
         ctx.fillStyle = "green";
         ctx.fill();
         ctx.closePath();
         if (rightDownPressed && r_PaddleY < canvas.height - r_PaddleHeight) {
            r_PaddleY += 7;
         }
         else if (rightUpPressed && r_PaddleY > 0) {
            r_PaddleY -= 7;
         }
      }

      function Scene() {
         // Draw center line
         ctx.beginPath();
         ctx.rect(canvas.width / 2 - 1, 0, 3, canvas.height);
         ctx.fillStyle = "white";
         ctx.fill();
         ctx.closePath();
      }
      
      function draw() {
         ctx.clearRect(0, 0, canvas.width, canvas.height);
         Scores();
         Scene();
         drawLeftPaddle();
         drawRightPaddle();
         Ball();
         computeCollisionsWithWallsAndPaddle();
         x += dx;
         y += dy;
      }

      // Start the game
      setInterval(draw, 10);
      document.addEventListener("keydown", DownHandler, false);
      document.addEventListener("keyup", UpHandler, false);
   </script>
</body>
</html>

How the Game Works

The game operates using a continuous game loop that updates 100 times per second:

  • Ball Movement: The ball moves continuously based on dx and dy velocity values

  • Collision Detection: Checks for collisions with paddles and walls

  • Scoring System: Points are awarded when the ball passes a paddle

  • Ball Reset: After scoring, the ball returns to center with reversed direction

Key Features

  • Responsive Controls: Smooth paddle movement with keyboard input

  • Collision Physics: Realistic ball bouncing off paddles and walls

  • Score Tracking: Live score display for both players

  • Visual Design: Classic Pong aesthetic with center line divider

Conclusion

This Pong game demonstrates fundamental game development concepts using HTML5 Canvas and JavaScript. The implementation includes collision detection, keyboard input handling, and a continuous game loop, making it a complete two-player gaming experience.

Updated on: 2026-03-15T23:19:00+05:30

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements