DEV Community

Cover image for Building a 2D Pong Game in JS
Riley
Riley

Posted on

Building a 2D Pong Game in JS

It's a simple game with two paddles, a ball, and a score counter. Even though Pong is an old game, building it can teach you a lot about game gameplay, animations, and handling user input.

So here I'll guide you through the process step by step...

Before we start, let's set up the basic structure of our project. First, you'll need a text editor like Visual Studio Code, Sublime Text, or Notepad++. Then, create a folder for your project, and inside that folder, create an HTML file and a JavaScript file.

Writing the HTML

Open your index.html file and start by setting up a basic HTML structure. We'll add the <canvas> element where we'll draw everything.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pong Game</title>
    <style>
        body {
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #000;
        }
        canvas {
            border: 2px solid #fff;
        }
    </style>
</head>
<body>
    <canvas id="pong" width="800" height="400"></canvas>
    <script src="script.js"></script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

So, we've set the width of the canvas to 800 pixels and the height to 400 pixels, which is a standard size for a 2D Pong game.

Now, let's move on to the JS part. This will be the core of the game.

Step 1: Set Up the Canvas

In the script.js file, start by selecting the canvas element and setting up the drawing context.

const canvas = document.getElementById("pong");
const ctx = canvas.getContext("2d");

Enter fullscreen mode Exit fullscreen mode

The canvas.getContext("2d") method gives us access to the drawing tools. We’ll use this to draw the paddles, ball, and score.

Step 2: Define the game objects

Next, we'll define the paddles and the ball. The paddles are rectangles, and the ball is a circle. Here's how you can define them:

// Paddle 1 (left)
const paddleWidth = 10, paddleHeight = 100;
const leftPaddle = {
    x: 0,
    y: canvas.height / 2 - paddleHeight / 2,
    width: paddleWidth,
    height: paddleHeight,
    color: "#00f",
    dy: 0 // Velocity of the paddle's movement
};

// Paddle 2 (right)
const rightPaddle = {
    x: canvas.width - paddleWidth,
    y: canvas.height / 2 - paddleHeight / 2,
    width: paddleWidth,
    height: paddleHeight,
    color: "#f00",
    dy: 0
};

// Ball
const ballRadius = 10;
const ball = {
    x: canvas.width / 2,
    y: canvas.height / 2,
    radius: ballRadius,
    color: "#fff",
    dx: 4, // Ball speed in X direction
    dy: 4  // Ball speed in Y direction
};

Enter fullscreen mode Exit fullscreen mode

Here, we've set the paddle height to 100 pixels, and the ball radius to 10 pixels. The ball's speed is set to 4 pixels per frame in both the X and Y directions.

Step 3: Draw the Game Objects
To render everything, we'll need a function to draw the paddles, ball, and score on the canvas. Let's write a draw() function:

function draw() {
    // Clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Draw paddles
    ctx.fillStyle = leftPaddle.color;
    ctx.fillRect(leftPaddle.x, leftPaddle.y, leftPaddle.width, leftPaddle.height);

    ctx.fillStyle = rightPaddle.color;
    ctx.fillRect(rightPaddle.x, rightPaddle.y, rightPaddle.width, rightPaddle.height);

    // Draw ball
    ctx.fillStyle = ball.color;
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
    ctx.fill();
}

Enter fullscreen mode Exit fullscreen mode

This function clears the canvas each frame and redraws the paddles and ball. The paddles are drawn using the fillRect() method, and the ball is drawn using the arc() method.

Step 4: Move the Ball and Paddles
Now, let's make the ball move. We'll update its position each frame. For the paddles, we'll also add movement. Here's the code to handle the ball and paddle movement:

function moveBall() {
    ball.x += ball.dx;
    ball.y += ball.dy;

    // Ball collision with top and bottom
    if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
        ball.dy = -ball.dy; // Reverse the Y direction
    }

    // Ball collision with paddles
    if (
        (ball.x - ball.radius < leftPaddle.x + leftPaddle.width && ball.y > leftPaddle.y && ball.y < leftPaddle.y + leftPaddle.height) ||
        (ball.x + ball.radius > rightPaddle.x && ball.y > rightPaddle.y && ball.y < rightPaddle.y + rightPaddle.height)
    ) {
        ball.dx = -ball.dx; // Reverse the X direction
    }

    // Ball out of bounds (left or right side)
    if (ball.x + ball.radius < 0 || ball.x - ball.radius > canvas.width) {
        // Reset ball position to the center
        ball.x = canvas.width / 2;
        ball.y = canvas.height / 2;
        ball.dx = 4; // Ball speed reset
        ball.dy = 4;
    }
}

function movePaddle(paddle) {
    paddle.y += paddle.dy;

    // Prevent paddle from going out of bounds
    if (paddle.y < 0) {
        paddle.y = 0;
    } else if (paddle.y + paddle.height > canvas.height) {
        paddle.y = canvas.height - paddle.height;
    }
}

Enter fullscreen mode Exit fullscreen mode

So in this function, the ball will bounce off the walls and paddles. The paddles can move up and down, but they won't go off the screen.

Step 5: Handle User Input
We need to allow the player to control the paddles. We'll add event listeners for the up and down arrow keys.

document.addEventListener("keydown", function (event) {
    if (event.key === "ArrowUp") {
        rightPaddle.dy = -5; // Move up
    } else if (event.key === "ArrowDown") {
        rightPaddle.dy = 5; // Move down
    }

    if (event.key === "w") {
        leftPaddle.dy = -5; // Move up
    } else if (event.key === "s") {
        leftPaddle.dy = 5; // Move down
    }
});

document.addEventListener("keyup", function (event) {
    if (event.key === "ArrowUp" || event.key === "ArrowDown") {
        rightPaddle.dy = 0; // Stop movement
    }

    if (event.key === "w" || event.key === "s") {
        leftPaddle.dy = 0; // Stop movement
    }
});

Enter fullscreen mode Exit fullscreen mode

The up and down arrow keys control the right paddle, while the W and S keys control the left paddle.

Putting It All Together
Finally, we need to call the functions in a game loop to make the game run continuously. Use requestAnimationFrame() to create a smooth animation loop:

function gameLoop() {
    draw();
    moveBall();
    movePaddle(leftPaddle);
    movePaddle(rightPaddle);
    requestAnimationFrame(gameLoop); // Call the gameLoop again
}

gameLoop(); // Start the game loop

Enter fullscreen mode Exit fullscreen mode

Finally...

And there you have it! You've now built a basic 2D Pong game in JS. This game isn't overly complex, but it gives you a good foundation for understanding how game mechanics work. You can further enhance it by adding features like scoring, sound effects, or AI for single player mode.

Quick intro about me: So I am nothing but a game developer and a gamer as well. Worked on many gaming projects like Spend Bill Gates Money a simulator game.

Top comments (0)