Skip to content

Instantly share code, notes, and snippets.

@straker straker/README.md

Last active Aug 13, 2020
Embed
What would you like to do?
Basic Pong HTML Game

Basic Pong HTML 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.

<!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="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>
@misterslime

This comment has been minimized.

Copy link

misterslime commented Sep 23, 2019

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>
@misterslime

This comment has been minimized.

Copy link

misterslime commented Sep 27, 2019

Is there any chance of a Tetris HTML game?

@straker

This comment has been minimized.

Copy link
Owner Author

straker commented Sep 28, 2019

👍

Sure, I'll make it the next one.

@millardoj

This comment has been minimized.

Copy link

millardoj commented Oct 30, 2019

what is the mobile code

@carfelipeson

This comment has been minimized.

Copy link

carfelipeson commented Mar 11, 2020

how do you controll it if your own a google sites

@Pro496951

This comment has been minimized.

@SKULLCODER1303

This comment has been minimized.

Copy link

SKULLCODER1303 commented Apr 21, 2020

Where is the mobile version of pong game?
is it multiplayer meaning when you install on website (mobile version) can 2 players play it from different devices.
Can I get a complete code of mobile version with score updation.

@ghost

This comment has been minimized.

Copy link

ghost commented Jun 4, 2020

can you make the ball slower by a little bit it is to fast for me to hit it

@straker

This comment has been minimized.

Copy link
Owner Author

straker commented Jun 4, 2020

@Pusheen13 if you change the ballSpeed to a lower number the ball will go slower https://gist.github.com/straker/81b59eecf70da93af396f963596dfdc5#file-pong-html-L29

@ghost

This comment has been minimized.

Copy link

ghost commented Jun 4, 2020

thanks

@ghost

This comment has been minimized.

Copy link

ghost commented Jun 9, 2020

wait can you add a score i can't keep track. Thanks @straker if you can

@ttoad29

This comment has been minimized.

Copy link

ttoad29 commented Jun 14, 2020

awesome!

@215917

This comment has been minimized.

Copy link

215917 commented Jun 19, 2020

Works great thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.