Skip to content

Instantly share code, notes, and snippets.

@straker
Last active March 24, 2024 16:21
Show Gist options
  • Star 46 You must be signed in to star a gist
  • Fork 21 You must be signed in to fork a gist
  • Save straker/81b59eecf70da93af396f963596dfdc5 to your computer and use it in GitHub Desktop.
Save straker/81b59eecf70da93af396f963596dfdc5 to your computer and use it in GitHub Desktop.
Basic Pong HTML and JavaScript Game

Basic Pong HTML and JavaScript Game

This is a basic implementation of the Atari Pong game, but it's missing a few things intentionally and they're left as further exploration for the reader.

Further Exploration

  • Score
    • When a ball goes past a paddle, the other player should score a point. Use context.fillText() to display the score to the screen
  • Mobile and touchscreen support
  • Ball trajectory
    • The ball should change trajectory based on where it hit the paddle. For example, if it hit the topmost part of the paddle it should have a sharp angle upward, whereas if it hit the direct middle of the paddle it should move completely flat towards the other payer.

Important note: I will answer questions about the code but will not add more features or answer questions about adding more features. This series is meant to give a basic outline of the game but nothing more.

License

(CC0 1.0 Universal) You're free to use this game and code in any project, personal or commercial. There's no need to ask permission before using these. Giving attribution is not required, but appreciated.

Other Basic Games

Support

Basic HTML Games are made possible by users like you. When you become a Patron, you get access to behind the scenes development logs, the ability to vote on which games I work on next, and early access to the next Basic HTML Game.

Top Patrons

  • Karar Al-Remahy
  • UnbrandedTech
  • Innkeeper Games
  • Nezteb
<!DOCTYPE html>
<html>
<head>
<title>Basic Pong HTML Game</title>
<meta charset="UTF-8">
<style>
html, body {
height: 100%;
margin: 0;
}
body {
background: black;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<canvas width="750" height="585" id="game"></canvas>
<script>
const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
const grid = 15;
const paddleHeight = grid * 5; // 80
const maxPaddleY = canvas.height - grid - paddleHeight;
var paddleSpeed = 6;
var ballSpeed = 5;
const leftPaddle = {
// start in the middle of the game on the left side
x: grid * 2,
y: canvas.height / 2 - paddleHeight / 2,
width: grid,
height: paddleHeight,
// paddle velocity
dy: 0
};
const rightPaddle = {
// start in the middle of the game on the right side
x: canvas.width - grid * 3,
y: canvas.height / 2 - paddleHeight / 2,
width: grid,
height: paddleHeight,
// paddle velocity
dy: 0
};
const ball = {
// start in the middle of the game
x: canvas.width / 2,
y: canvas.height / 2,
width: grid,
height: grid,
// keep track of when need to reset the ball position
resetting: false,
// ball velocity (start going to the top-right corner)
dx: ballSpeed,
dy: -ballSpeed
};
// check for collision between two objects using axis-aligned bounding box (AABB)
// @see https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
function collides(obj1, obj2) {
return obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y;
}
// game loop
function loop() {
requestAnimationFrame(loop);
context.clearRect(0,0,canvas.width,canvas.height);
// move paddles by their velocity
leftPaddle.y += leftPaddle.dy;
rightPaddle.y += rightPaddle.dy;
// prevent paddles from going through walls
if (leftPaddle.y < grid) {
leftPaddle.y = grid;
}
else if (leftPaddle.y > maxPaddleY) {
leftPaddle.y = maxPaddleY;
}
if (rightPaddle.y < grid) {
rightPaddle.y = grid;
}
else if (rightPaddle.y > maxPaddleY) {
rightPaddle.y = maxPaddleY;
}
// draw paddles
context.fillStyle = 'white';
context.fillRect(leftPaddle.x, leftPaddle.y, leftPaddle.width, leftPaddle.height);
context.fillRect(rightPaddle.x, rightPaddle.y, rightPaddle.width, rightPaddle.height);
// move ball by its velocity
ball.x += ball.dx;
ball.y += ball.dy;
// prevent ball from going through walls by changing its velocity
if (ball.y < grid) {
ball.y = grid;
ball.dy *= -1;
}
else if (ball.y + grid > canvas.height - grid) {
ball.y = canvas.height - grid * 2;
ball.dy *= -1;
}
// reset ball if it goes past paddle (but only if we haven't already done so)
if ( (ball.x < 0 || ball.x > canvas.width) && !ball.resetting) {
ball.resetting = true;
// give some time for the player to recover before launching the ball again
setTimeout(() => {
ball.resetting = false;
ball.x = canvas.width / 2;
ball.y = canvas.height / 2;
}, 400);
}
// check to see if ball collides with paddle. if they do change x velocity
if (collides(ball, leftPaddle)) {
ball.dx *= -1;
// move ball next to the paddle otherwise the collision will happen again
// in the next frame
ball.x = leftPaddle.x + leftPaddle.width;
}
else if (collides(ball, rightPaddle)) {
ball.dx *= -1;
// move ball next to the paddle otherwise the collision will happen again
// in the next frame
ball.x = rightPaddle.x - ball.width;
}
// draw ball
context.fillRect(ball.x, ball.y, ball.width, ball.height);
// draw walls
context.fillStyle = 'lightgrey';
context.fillRect(0, 0, canvas.width, grid);
context.fillRect(0, canvas.height - grid, canvas.width, canvas.height);
// draw dotted line down the middle
for (let i = grid; i < canvas.height - grid; i += grid * 2) {
context.fillRect(canvas.width / 2 - grid / 2, i, grid, grid);
}
}
// listen to keyboard events to move the paddles
document.addEventListener('keydown', function(e) {
// up arrow key
if (e.which === 38) {
rightPaddle.dy = -paddleSpeed;
}
// down arrow key
else if (e.which === 40) {
rightPaddle.dy = paddleSpeed;
}
// w key
if (e.which === 87) {
leftPaddle.dy = -paddleSpeed;
}
// a key
else if (e.which === 83) {
leftPaddle.dy = paddleSpeed;
}
});
// listen to keyboard events to stop the paddle if key is released
document.addEventListener('keyup', function(e) {
if (e.which === 38 || e.which === 40) {
rightPaddle.dy = 0;
}
if (e.which === 83 || e.which === 87) {
leftPaddle.dy = 0;
}
});
// start the game
requestAnimationFrame(loop);
</script>
</body>
</html>
@jdiab1207
Copy link

How do you add a score?

@NXX99
Copy link

NXX99 commented Oct 1, 2021

I made a Basic Gun Fight HTML Game using the pong game's code.

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <style>
  html, body {
    height: 100%;
    margin: 0;
  }
  body {
    background: black;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  </style>
</head>
<body>
<canvas width="565" height="500" id="game"></canvas>
<script>
const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
const grid = 15;
const playerHeight = grid * 3; // 45
const maxPlayerY = canvas.height - grid - playerHeight;

var playerSpeed = 4;

const leftPlayer = {
  // start in the middle of the game on the left side
  x: grid * 2,
  y: canvas.height / 2 - playerHeight / 2,
  width: grid,
  height: playerHeight,
  
  // shooting cooldown
  cooldown: 0,
  
  // player velocity
  dy: 0
};

const rightPlayer = {
  // start in the middle of the game on the right side
  x: canvas.width - grid * 3,
  y: canvas.height / 2 - playerHeight / 2,
  width: grid,
  height: playerHeight,
  
  // shooting cooldown
  cooldown: 0,
  
  // player velocity
  dy: 0
};

const bullets = {
  speed: 5,
  array: []
}

// check for collision between two objects using axis-aligned bounding box (AABB)
// @see https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
function collides(obj1, obj2) {
  return obj1.x < obj2.x + obj2.width &&
         obj1.x + obj1.width > obj2.x &&
         obj1.y < obj2.y + obj2.height &&
         obj1.y + obj1.height > obj2.y;
}

// game loop
function loop() {
  requestAnimationFrame(loop);
  context.clearRect(0,0,canvas.width,canvas.height);
  
  // bullet cooldowns
  // left player
  if (leftPlayer.cooldown > 0) {
    leftPlayer.cooldown--;
  }
  // right player
  if (rightPlayer.cooldown > 0) {
    rightPlayer.cooldown--;
  }
  
  // move players by their velocity
  leftPlayer.y += leftPlayer.dy;
  rightPlayer.y += rightPlayer.dy;
  
  // prevent players from going through walls
  if (leftPlayer.y < grid) {
    leftPlayer.y = grid;
  }
  else if (leftPlayer.y > maxPlayerY) {
    leftPlayer.y = maxPlayerY;
  }
  
  if (rightPlayer.y < grid) {
    rightPlayer.y = grid;
  }
  else if (rightPlayer.y > maxPlayerY) {
    rightPlayer.y = maxPlayerY;
  }
  
  // draw bullets
  context.fillStyle = 'yellow';
  bullets.array.forEach(function(bullet, index) {
    context.fillRect(bullet.x, bullet.y, 10, 5);
	
	// check if the bullet hits a player
	// left player
	if (collides(bullet, leftPlayer)) {
	  bullets.array.splice(index, 1);
	  leftPlayer.y = canvas.height / 2 - playerHeight / 2;
	  rightPlayer.y = canvas.height / 2 - playerHeight / 2;
	  bullets.array.length = 0;
	}
	// right player
	else if (collides(bullet, rightPlayer)) {
	  bullets.array.splice(index, 1);
	  leftPlayer.y = canvas.height / 2 - playerHeight / 2;
	  rightPlayer.y = canvas.height / 2 - playerHeight / 2;
	  bullets.array.length = 0;
	}
    
    // move bullets
    bullet.x += bullet.dx;
	
	// remove bullets that leave the screen
    if (bullet.x < 0 || bullet.x > canvas.width) {
      bullets.array.splice(index, 1);
    }
  });
  
  // draw paddles
  context.fillStyle = 'gold';
  context.fillRect(leftPlayer.x, leftPlayer.y, leftPlayer.width, leftPlayer.height);
  context.fillRect(rightPlayer.x, rightPlayer.y, rightPlayer.width, rightPlayer.height);

  // draw walls
  context.fillStyle = 'lightgray';
  context.fillRect(0, 0, canvas.width, grid);
  context.fillRect(0, canvas.height - grid, canvas.width, canvas.height);
}

// listen to keyboard events to move the players
document.addEventListener('keydown', function(e) {
  // up arrow key
  if (e.which === 38) {
    rightPlayer.dy = -playerSpeed;
  }
  // down arrow key
  else if (e.which === 40) {
    rightPlayer.dy = playerSpeed;
  }
  
  // w key
  if (e.which === 87) {
    leftPlayer.dy = -playerSpeed;
  }
  // a key
  else if (e.which === 83) {
    leftPlayer.dy = playerSpeed;
  }
  
  // shooting
  // left arrow key
  if (e.which === 37 && rightPlayer.cooldown === 0) {
    bullets.array.push({
	  x: rightPlayer.x - 10, 
	  y: rightPlayer.y + 20, 
	  width: 10,
	  height: 5,
	  dx: -bullets.speed
	});
	rightPlayer.cooldown = 25;
  }
  // d key
  if (e.which === 68 && leftPlayer.cooldown === 0) {
    bullets.array.push({
	  x: leftPlayer.x + 15, 
	  y: leftPlayer.y + 20, 
	  width: 10,
	  height: 5,
	  dx: bullets.speed
	});
	leftPlayer.cooldown = 25;
  }
});
// listen to keyboard events to stop the player if key is released
document.addEventListener('keyup', function(e) {
  if (e.which === 38 || e.which === 40) {
    rightPlayer.dy = 0;
  }
  
  if (e.which === 83 || e.which === 87) {
    leftPlayer.dy = 0;
  }
});
// start the game
requestAnimationFrame(loop);
</script>
</body>
</html>

I made a game website with all of his games, plus your game. https://sites.google.com/k12.tasd7.net/htmlarcade/home

Copy link

ghost commented Oct 14, 2021

how did you made this please answer

@RelastDomax
Copy link

RelastDomax commented Oct 16, 2021 via email

@25anderh
Copy link

how would i make the left paddle follow the ball so i would be able to play with myself controlling the right?

@Tyis201
Copy link

Tyis201 commented Mar 9, 2022

how would you make it where there's only 1 paddle and the ball bounces off the back wall as well.

@Gloyworm
Copy link

Is there a way I'd be able to replace paddles and the ball with an image? Such as a hand. Thank you!

@max1444
Copy link

max1444 commented Mar 29, 2022

👍

Sure, I'll make it the next one.

hey could you make a tic tac toe game in html idont know if your still active but i love your work and i would love too see one thank you

@straker
Copy link
Author

straker commented Mar 29, 2022

Yep. I just did a poll for the next game on Patreon, so I can add tic-tac-toe to the next poll.

@max1444
Copy link

max1444 commented Mar 31, 2022

how would i make the left paddle follow the ball so i would be able to play with myself controlling the right?

yea could you make an ai doing this becuase i put this on a my website and alot of people are asking me to make an ai and ive only been coding for 1 year so i dont know how to make an ai

@codejaaa
Copy link

to cool

@zinoobux
Copy link

ty so cool and full function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment