Building a Ping Pong Game with HTML, CSS, and JavaScript: A Step-by-Step Guide

Wasiu Akindoyin
Web 3 Digitals
Published in
8 min readApr 3, 2024

· Introduction
· Project Overview
· Features of the Ping Pong Game
· Prerequisites
· Code Structure
Step 1. HTML Structure:
Step 2. CSS Styling:
Step 3. JavaScript Logic:
· Lessons Learned
· Directions to Play
· Deployment
· Future Improvements
· Conclusion

Introduction

This project will assist you in creating your own enjoyable and interactive ping-pong game using the fundamental elements of web development: HTML, CSS, and JavaScript. Throughout the process, you will acquire important skills in animation, user engagement, and essential game principles. This serves as an excellent introduction to the dynamic field of web development!

Project Overview

This project will help you build a fun and playable ping-pong game using the building blocks of web development: HTML, CSS, and JavaScript. Along the way, you’ll pick up valuable skills in animation, user interaction, and core game mechanics. This is a great first step into the exciting world of web development!

Features of the Ping Pong Game

In this project, you are going to develop a Ping Pong game with the following features:

  • Two-Player Paddles: The game includes paddles for both the user and the computer, allowing for interactive gameplay.
  • Ball Movement: A ball moves between the paddles, requiring players to hit it back and forth to keep the game going.
  • Score Tracking: The game keeps track of the score for both players, updating it whenever a player scores a point.
  • Start, Pause, and Restart Buttons: These buttons allow players to control the game, starting, pausing, and restarting as needed.
  • Simple AI: The game includes a simple AI for controlling the computer paddle, adding an element of challenge for single-player games.

Prerequisites

To build this Ping Pong game, you’ll need a basic understanding of HTML, CSS, and JavaScript. You should be familiar with HTML for structuring the application, CSS for styling it, and JavaScript for implementing the logic of the application.

A text editor or IDE (e.g., Visual Studio Code) is required for writing code, and a web browser is needed for testing. Optional prerequisites include a GitHub account for hosting the application.

Code Structure

Create a new folder for your project, name the folder as you wish, and inside it, create three files named index.html, style.css, and script.js. These files will serve as the foundation for your project. Now open the folder in a text editor or IDE (e.g., Visual Studio Code) and follow the steps below:

Step 1. HTML Structure:

Open theindex.html file and paste the following HTML code for the Ping Pong game:

<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
<title>Ping Pong Game</title>
</head>
<body>
<div class="header">
<img src="./Image/pngkit_ping-pong-ball-png_1477974.png" alt="logo" width="60px">
<div class="buttons">
<button class="start-btn">Start</button>
<button class="pause-btn">Pause</button>
<button class="restart-btn">Restart</button>
</div>
</div>

<div class="pong-wrapper">
<canvas id="ping-pong" width="600px" height="400px"></canvas>
</div>
</body>
</html>

The HTML code above sets up a basic structure for the ping pong game. It includes a header with buttons for starting, pausing, and restarting the game, as well as an image logo. The main game area is a canvas element with an id of ping-pong for rendering the game.

The document includes links to an external CSS file for styling and a JavaScript file for game functionality, with the script tag set to defer for optimal loading.

Step 2. CSS Styling:

Open thestyle.css file and paste the following CSS code to style the Ping Pong game:

*{
margin: 0;
padding: 0;
box-sizing: border-box;
}

body{
background-color: darkgrey;
}

.header {
display: flex;
align-items: center;
justify-content: space-around;
padding: 0.1em;
margin-top: 0.1em;
background-color: green;
}

.header img {
width: 60px;
}

.buttons button {
letter-spacing: 2px;
text-transform: uppercase;
border: none;
color: white;
background-color: green;
padding: 10px;
letter-spacing: 1px;
font-size: 1em;
font-weight: bold;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
}

.buttons button:hover {
text-decoration: underline;
font-size: 1.05em;
}

.pong-wrapper {
display: flex;
justify-content: center;
align-items: center;
margin-top: 3em;
}

#ping-pong {
width: 80%;
max-width: 680px;
border: 12px solid white;
}

@media screen and (max-width: 480px) {
.header img {
width: 40px;
}
.buttons button {
letter-spacing: 1px;
padding: 5px;
letter-spacing: 1px;
font-size: 0.7em;
}

.buttons button:hover {
text-decoration: underline;
font-size: 1.05em;
}
}

This CSS code styles the ping-pong game interface. It includes styles for the body, a header with buttons and a logo, and the main game area. Media queries are used to adjust styles for smaller screens.

Step 3. JavaScript Logic:

Open thescript.js file and add functionality to the Ping Pong game using the following JavaScript code:

const canvas = document.querySelector("#ping-pong");

const context = canvas.getContext("2d");

const startBtn = document.querySelector(".start-btn");

const pauseBtn = document.querySelector(".pause-btn");

const restartBtn = document.querySelector(".restart-btn");

let gameRunning = false;

let animationId;

//CREATE USER PADDLE
const user = {
x: 0,
y: canvas.height/2 - 100/2,
width: 10,
height: 100,
color: "red",
score: 0
}

//CREATE COMPUTER PADDLE
const computer = {
x: canvas.width - 10,
y: canvas.height/2 - 100/2,
width: 10,
height: 100,
color: "black",
score: 0
}

//CREATE THE BALL
const ball = {
x: canvas.width / 2,
y: canvas.height / 2,
radius: 10,
speed: 5,
velocityX: 5,
velocityY: 5,
color: "white"
}

//CREATE THE NET
const net = {
x: canvas.width/2 - 1,
y: 0,
width: 2,
height: 10,
color: "white"
}

restartBtn.addEventListener("click", () => {
document.location.reload();
});

addEventListener("load", (event) => {
render();
});

//DRAW NET FUNCTION
function drawNet() {
const netWidth = 4; // Adjust the net width as needed
const netSpacing = 15; // Adjust the spacing as needed

// Draw the left half of the net
for (let i = 0; i <= canvas.height; i += netSpacing) {
drawRectangle(net.x, net.y + i, netWidth, net.height, net.color);
}

// Draw the right half of the net
for (let i = 0; i <= canvas.height; i += netSpacing) {
drawRectangle(net.x + net.width - netWidth, net.y + i, netWidth, net.height, net.color);
}
}


//DRAW RECTANGLE FUNCTION
function drawRectangle(x, y, w, h, color) {
context.fillStyle = color;
context.fillRect(x, y, w, h);
}

//DRAW CIRCLE FUNCTION
function drawCircle(x, y, r, color) {
context.fillStyle = color;
context.beginPath();
context.arc(x, y, r, 0, Math.PI * 2, false);
context.closePath();
context.fill();
}

//DRAW TEXT FUNCTION
function drawText(text, x, y, color) {
context.fillStyle = color;
context.font = "45px fantasy";
context.fillText(text, x, y);
}

//RENDER GAME FUNCTION
// Inside the render() function
function render() {
// CLEAR THE CANVAS
drawRectangle(0, 0, canvas.width, canvas.height, "green");

// DRAW THE NET
drawNet();

// DRAW THE SCORE
drawText(user.score, canvas.width / 4, canvas.height / 5, "white");
drawText(computer.score, (3 * canvas.width) / 4, canvas.height / 5, "white");

// DRAW THE USER AND COMPUTER PADDLES
drawRectangle(user.x, user.y, user.width, user.height, user.color);
drawRectangle(computer.x, computer.y, computer.width, computer.height, computer.color);

// DRAW THE BALL
drawCircle(ball.x, ball.y, ball.radius, ball.color);

// DRAW THE WHITE LINE IN THE MIDDLE
drawRectangle(net.x, net.y, net.width, canvas.height, net.color);
}

//CONTROL USERS PADDLE
canvas.addEventListener("mousemove", movePaddle);

function movePaddle(evt) {
let rectangle = canvas.getBoundingClientRect();

user.y = evt.clientY - rectangle.top - user.height/2;
}

//COLLISION DETECTION FUNCTION
function collision(b, p) {
b.top = b.y - b.radius;
b.bottom = b.y + b.radius;
b.left = b.x - b.radius;
b.right = b.x + b.radius;

p.top = p.y;
p.bottom = p.y + p.height;
p.left = p.x;
p.right = p.x + p.width;

return b.right > p.left && b.bottom > p.top && b.left < p.right && b.top < p.bottom;
}

//RESET BALL FUNCTION
function resetBall() {
ball.x = canvas.width / 2;
ball.y = canvas.height / 2;

ball.speed = 5;
ball.velocityX = -ball.velocityX;
}

//UPDATE FUNCTION
function update() {
ball.x += ball.velocityX;
ball.y += ball.velocityY;

//SIMPLE AI TO CONTROL THE COMPUTER PADDLE
let computerLevel = 0.1;
computer.y += (ball.y - (computer.y + computer.height/2)) * computerLevel;

if(ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
ball.velocityY = -ball.velocityY;
}

let player = (ball.x < canvas.width/2) ? user : computer;

if(collision(ball, player)) {
//WHERE THE BALL HIT THE PLAYER
let collidePoint = ball.y - (player.y + player.height/2);

//NORMALIZATION
collidePoint = collidePoint / (player.height/2);

//CALCULATE THE ANGLE IN RADIAN
let angleRad = collidePoint * Math.PI/4;

//X DIRECTION OF THE BALL WHEN IT'S HIT
let direction = (ball.x < canvas.width/2) ? 1 : -1;


//CHANGE VELOCITY OF X AND Y
ball.velocityX = direction * ball.speed * Math.cos(angleRad);

ball.velocityY = ball.speed * Math.sin(angleRad);

//Everytime a ball is hit by a paddle, we increase its speed
ball.speed += 0.5;
}
//UPDATE THE SCORE
if(ball.x - ball.radius < 0) {
//THE COMPUTER GAINS 1 POINT
computer.score++;
resetBall();
} else if(ball.x + ball.radius > canvas.width){
//THE USER GAINS 1 POINT
user.score++;
resetBall();
}
}

//GAME INITIALIZATION FUNCTION
function animate() {
if(!gameRunning) {
return; // Don't continue the animation if it's paused
}

update();
render();
animationId = requestAnimationFrame(animate);
}


startBtn.addEventListener("click", () => {
if (!gameRunning) {
gameRunning = true;
animate();
}
});

pauseBtn.addEventListener("click", () => {
gameRunning = false;
cancelAnimationFrame(animationId);
});

The JavaScript code above sets up the ping-pong game using HTML canvas and JavaScript. It creates user and computer paddles, a ball, a net, and handles game logic like collision detection, scoring, and paddle movement. It includes event listeners for game controls like start, pause, and restart buttons.

It includes functions to draw shapes on the canvas, update game elements, and animate the game loop. The computer paddle has a simple AI to follow the ball’s vertical position. Scoring is based on the ball going past the paddles. The game speed increases each time the ball hits a paddle.

Lessons Learned

This project taught me the importance of planning and designing the game logic before diving into coding. I also improved my understanding of CSS stylings, JavaScript events, and DOM manipulation, which are crucial for creating interactive web applications.

Directions to Play

To play the Ping Pong game, follow these steps:

  • Start the Game: Click the START button to begin the game. This will start the ball moving, and the paddles will be controlled by you, the user, and the computer.
  • Control Your Paddle: Move your paddle (i.e., red paddle) up and down to hit the ball using your mouse on your desktop.
  • Hit the Ball: Try to hit the ball with your paddle to keep it in play. If the ball passes your paddle and reaches the edge of the screen behind you, your opponent scores a point.
  • Score Points: Each time the ball passes your opponent’s paddle and reaches the edge of the screen behind them, you score a point.
  • Win the Game: Continue playing until one player reaches a set number of points or until you decide to stop the game. You can PAUSE or RESTART the game using the corresponding buttons.

Deployment

The Ping Pong game project is hosted on GitHub Pages and can be played online by visiting the following link:

Play the Game: https://wasiu-akindoyin.github.io/Ping-Pong-Game-Web-Application/

You can access the GitHub repository here to view or contribute to the source code.

Future Improvements

In the future, I plan to add more features to the game, such as:

  • Improved responsiveness for mobile devices allows players to enjoy the game on their phones because this current version is desktop-based
  • Support for multiple players
  • Enhanced graphics and animations
  • Integration with a backend server to store player scores and game history

Conclusion

Building the Ping Pong game with HTML, CSS, and JavaScript was a challenging but rewarding experience. I believe you have gained valuable insights into game development and JavaScript programming. I urge you to play the game and explore the code to enhance your understanding of front-end development.

If you find this project guide helpful, please clap, share, and follow me to learn more about front-end development, blockchain networks, and a whole lot more. Thank you for sticking around till the end, and see you on the next one.

--

--

Wasiu Akindoyin
Web 3 Digitals

Front-end Developer | Technical Writer | Simplifying complex software concepts through code and real life analogies.