Pong Game in JavaScript

22 Feb, 2021
Pong game is a two-player table tennis-themed video game. The game involves two paddles and a moving ball. The players have to move paddles in an upwards or downwards direction and save the ball from getting hit onto the wall. If the ball hits the wall then it’s a score for another player.
Prerequisite: Must be aware of HTML, CSS, JavaScript.
Procedure:
Create an HTML file with the name index.html.
Create a CSS file with the name styles.css and link it in the index.html file using the link tag.
Create a JS file with the name index.js and link it in the index.html file using a script tag.
Create a div for the game board, ball, and 2 divs for paddles, i.e. player-1 and player-2.
Give some style to your game in the CSS file.
Get a reference to paddles, balls, and game boards in JS.
Create a function in the index.js file with the name move ball.
Give the ball a random direction and a random speed by changing the x and y coordinates of the ball.
Apply collision with ball and game board’s top/bottom side, i.e. if the ball touches the top/bottom of the board then multiply -1 * y velocity of the ball.
Apply collision with ball and game left and right side of the game board. i.e. increase the score and change game state to serve the state.
Apply collision with ball and paddles. i.e. multiply -1 * x velocity of the ball.
Direction to play:
To Start the Game Press the “ENTER” key.
Player 1: Player 1 can control the left side paddle i.e, PADDLE_1 by using the ‘W‘ key to move upwards and to go downwards ‘S‘ key should be used.
Player 2: Player 2 can control the left side paddle i.e, PADDLE_2 by using the ‘UP Arrow‘ key to move upwards and to go downwards ‘Down Arrow‘ key should be used.
HTML Code:
HTML
<!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>    <link rel="stylesheet" href="style.css"></head>  <body>    <div class="board">        <div class='ball'>            <div class="ball_effect"></div>        </div>        <div class="paddle_1 paddle"></div>        <div class="paddle_2  paddle"></div>        <h1 class="player_1_score">0</h1>        <h1 class="player_2_score">0</h1>        <h1 class="message">            Press Enter to Play Pong        </h1>    </div>          <script src="index.js"></script></body>  </html>
CSS Code:
* {    margin: 0;    padding: 0;    box-sizing: border-box;}  body {    height: 100vh;    width: 100vw;    background-image: linear-gradient(            to top, #ffda77, #ffa45b);    display: flex;    justify-content: center;    align-items: center;}  .board {    height: 85vh;    width: 80vw;    background-image: linear-gradient(            to right, #5c6e91, #839b97);    border-radius: 14px;}  .ball {    height: 30px;    width: 30px;    border-radius: 50%;    position: fixed;    top: calc(50% - 15px);    left: calc(50% - 15px);}  .ball_effect {    height: 100%;    width: 100%;    border-radius: 100px;    animation: spinBall 0.1s linear infinite;    box-shadow: inset 0 0 18px #fff,         inset 6px 0 18px violet,         inset -6px 0 18px #0ff,         inset 6px 0 30px violet,         inset -6px 0 30px #0ff,         0 0 18px #fff, -4px 0 18px         violet, 4px 0 18px #0ff;}  @keyframes spinBall {    100% {        -webkit-transform: rotate(360deg);        transform: rotate(360deg);    }}  .paddle {    height: 100px;    width: 18px;    border-radius: 50%;    position: fixed;}  .paddle_1 {    top: calc(7.5vh + 55px);    left: calc(10vw + 30px);    box-shadow: inset 0 0 18px #fff,         inset -6px 0 18px #f3bad6,         inset 6px 0 18px #0ff,         inset -6px 0 30px #f3bad6,         inset 6px 0 30px #0ff,         0 0 18px #fff, 4px 0 18px         #f3bad6, -4px 0 18px #0ff;}  .paddle_2 {    top: calc(85vh + 7.5vh - 100px - 55px);    right: calc(10vw + 30px);    box-shadow: inset 0 0 18px #fff,         inset 6px 0 18px #f3bad6,         inset -6px 0 18px #0ff,         inset 6px 0 30px #f3bad6,         inset -6px 0 30px #0ff,         0 0 18px #fff, -4px 0 18px         #f3bad6, 4px 0 18px #0ff;}  .player_1_score {    height: 50px;    width: 50px;    color: chartreuse;    position: fixed;    left: 30vw;    margin-top: 30px;}  .player_2_score {    height: 50px;    width: 50px;    color: chartreuse;    position: fixed;    left: 70vw;    margin-top: 30px;}  .message {    position: fixed;    /* color: #48426d; */    height: 10vh;    width: 30vw;    color: #c9cbff;    left: 38vw;    margin: 30px auto auto auto;}
JavaScript Code:
Javascript
let gameState = 'start';let paddle_1 = document.querySelector('.paddle_1');let paddle_2 = document.querySelector('.paddle_2');let board = document.querySelector('.board');let initial_ball = document.querySelector('.ball');let ball = document.querySelector('.ball');let score_1 = document.querySelector('.player_1_score');let score_2 = document.querySelector('.player_2_score');let message = document.querySelector('.message');let paddle_1_coord = paddle_1.getBoundingClientRect();let paddle_2_coord = paddle_2.getBoundingClientRect();let initial_ball_coord = ball.getBoundingClientRect();let ball_coord = initial_ball_coord;let board_coord = board.getBoundingClientRect();let paddle_common =     document.querySelector('.paddle').getBoundingClientRect();  let dx = Math.floor(Math.random() * 4) + 3;let dy = Math.floor(Math.random() * 4) + 3;let dxd = Math.floor(Math.random() * 2);let dyd = Math.floor(Math.random() * 2);  document.addEventListener('keydown', (e) => {  if (e.key == 'Enter') {    gameState = gameState == 'start' ? 'play' : 'start';    if (gameState == 'play') {      message.innerHTML = 'Game Started';      message.style.left = 42 + 'vw';      requestAnimationFrame(() => {        dx = Math.floor(Math.random() * 4) + 3;        dy = Math.floor(Math.random() * 4) + 3;        dxd = Math.floor(Math.random() * 2);        dyd = Math.floor(Math.random() * 2);        moveBall(dx, dy, dxd, dyd);      });    }  }  if (gameState == 'play') {    if (e.key == 'w') {      paddle_1.style.top =        Math.max(          board_coord.top,          paddle_1_coord.top - window.innerHeight * 0.06        ) + 'px';      paddle_1_coord = paddle_1.getBoundingClientRect();    }    if (e.key == 's') {      paddle_1.style.top =        Math.min(          board_coord.bottom - paddle_common.height,          paddle_1_coord.top + window.innerHeight * 0.06        ) + 'px';      paddle_1_coord = paddle_1.getBoundingClientRect();    }      if (e.key == 'ArrowUp') {      paddle_2.style.top =        Math.max(          board_coord.top,          paddle_2_coord.top - window.innerHeight * 0.1        ) + 'px';      paddle_2_coord = paddle_2.getBoundingClientRect();    }    if (e.key == 'ArrowDown') {      paddle_2.style.top =        Math.min(          board_coord.bottom - paddle_common.height,          paddle_2_coord.top + window.innerHeight * 0.1        ) + 'px';      paddle_2_coord = paddle_2.getBoundingClientRect();    }  }});  function moveBall(dx, dy, dxd, dyd) {  if (ball_coord.top <= board_coord.top) {    dyd = 1;  }  if (ball_coord.bottom >= board_coord.bottom) {    dyd = 0;  }  if (    ball_coord.left <= paddle_1_coord.right &&    ball_coord.top >= paddle_1_coord.top &&    ball_coord.bottom <= paddle_1_coord.bottom  ) {    dxd = 1;    dx = Math.floor(Math.random() * 4) + 3;    dy = Math.floor(Math.random() * 4) + 3;  }  if (    ball_coord.right >= paddle_2_coord.left &&    ball_coord.top >= paddle_2_coord.top &&    ball_coord.bottom <= paddle_2_coord.bottom  ) {    dxd = 0;    dx = Math.floor(Math.random() * 4) + 3;    dy = Math.floor(Math.random() * 4) + 3;  }  if (    ball_coord.left <= board_coord.left ||    ball_coord.right >= board_coord.right  ) {    if (ball_coord.left <= board_coord.left) {      score_2.innerHTML = +score_2.innerHTML + 1;    } else {      score_1.innerHTML = +score_1.innerHTML + 1;    }    gameState = 'start';      ball_coord = initial_ball_coord;    ball.style = initial_ball.style;    message.innerHTML = 'Press Enter to Play Pong';    message.style.left = 38 + 'vw';    return;  }  ball.style.top = ball_coord.top + dy * (dyd == 0 ? -1 : 1) + 'px';  ball.style.left = ball_coord.left + dx * (dxd == 0 ? -1 : 1) + 'px';  ball_coord = ball.getBoundingClientRect();  requestAnimationFrame(() => {    moveBall(dx, dy, dxd, dyd);  });}
Combine Code:
HTML
<!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>      *{        margin: 0;        padding: 0;        box-sizing: border-box;      }        body {        height: 100vh;        width: 100vw;        background-image: linear-gradient(to top, #ffda77, #ffa45b);        display: flex;        justify-content: center;        align-items: center;      }        .board {        height: 85vh;        width: 80vw;        background-image: linear-gradient(to right, #5c6e91, #839b97);        border-radius: 14px;      }        .ball {        height: 30px;        width: 30px;        border-radius: 50%;        position: fixed;        top: calc(50% - 15px);        left: calc(50% - 15px);      }        .ball_effect {        height: 100%;        width: 100%;        border-radius: 100px;        animation: spinBall 0.1s linear infinite;        box-shadow: inset 0 0 18px #fff, inset 6px 0 18px violet,          inset -6px 0 18px #0ff, inset 6px 0 30px violet,           inset -6px 0 30px #0ff, 0 0 18px #fff,           -4px 0 18px violet, 4px 0 18px #0ff;      }        @keyframes spinBall {        100% {          -webkit-transform: rotate(360deg);          transform: rotate(360deg);        }      }        .paddle {        height: 100px;        width: 18px;        border-radius: 50%;        position: fixed;      }        .paddle_1 {        top: calc(7.5vh + 55px);        left: calc(10vw + 30px);        box-shadow: inset 0 0 18px #fff,           inset -6px 0 18px #f3bad6,          inset 6px 0 18px #0ff, inset -6px 0 30px #f3bad6,           inset 6px 0 30px #0ff, 0 0 18px #fff,           4px 0 18px #f3bad6, -4px 0 18px #0ff;      }        .paddle_2 {        top: calc(85vh + 7.5vh - 100px - 55px);        right: calc(10vw + 30px);        box-shadow: inset 0 0 18px #fff,           inset 6px 0 18px #f3bad6,          inset -6px 0 18px #0ff, inset 6px 0 30px #f3bad6,          inset -6px 0 30px #0ff,          0 0 18px #fff, -4px 0 18px #f3bad6, 4px 0 18px #0ff;      }        .player_1_score {        height: 50px;        width: 50px;        color: chartreuse;        position: fixed;        left: 30vw;        margin-top: 30px;      }        .player_2_score {        height: 50px;        width: 50px;        color: chartreuse;        position: fixed;        left: 70vw;        margin-top: 30px;      }        .message {        position: fixed;        /* color: #48426d; */        height: 10vh;        width: 30vw;        color: #c9cbff;        left: 38vw;        margin: 30px auto auto auto;      }    </style></head>    <body>  <div class="board">      <div class='ball'>        <div class="ball_effect"></div>      </div>      <div class="paddle_1 paddle"></div>      <div class="paddle_2  paddle"></div>      <h1 class = "player_1_score">0</h1>      <h1 class="player_2_score">0</h1>      <h1 class="message">        Press Enter to Play Pong      </h1>  </div>  <script>    let gameState = 'start';    let paddle_1 = document.querySelector('.paddle_1');    let paddle_2 = document.querySelector('.paddle_2');    let board = document.querySelector('.board');    let initial_ball = document.querySelector('.ball');    let ball = document.querySelector('.ball');    let score_1 = document.querySelector('.player_1_score');    let score_2 = document.querySelector('.player_2_score');    let message = document.querySelector('.message');    let paddle_1_coord = paddle_1.getBoundingClientRect();    let paddle_2_coord = paddle_2.getBoundingClientRect();    let initial_ball_coord = ball.getBoundingClientRect();    let ball_coord = initial_ball_coord;    let board_coord = board.getBoundingClientRect();    let paddle_common =         document.querySelector('.paddle').getBoundingClientRect();    let dx = Math.floor(Math.random() * 4) + 3;    let dy = Math.floor(Math.random() * 4) + 3;    let dxd = Math.floor(Math.random() * 2);    let dyd = Math.floor(Math.random() * 2);      document.addEventListener('keydown', (e) => {      if (e.key == 'Enter') {        gameState = gameState == 'start' ? 'play' : 'start';        if (gameState == 'play') {          message.innerHTML = 'Game Started';          message.style.left = 42 + 'vw';          requestAnimationFrame(() => {            dx = Math.floor(Math.random() * 4) + 3;            dy = Math.floor(Math.random() * 4) + 3;            dxd = Math.floor(Math.random() * 2);            dyd = Math.floor(Math.random() * 2);            moveBall(dx, dy, dxd, dyd);          });        }      }      if (gameState == 'play') {        if (e.key == 'w') {          paddle_1.style.top =            Math.max(              board_coord.top,              paddle_1_coord.top - window.innerHeight * 0.06            ) + 'px';          paddle_1_coord = paddle_1.getBoundingClientRect();        }        if (e.key == 's') {          paddle_1.style.top =            Math.min(              board_coord.bottom - paddle_common.height,              paddle_1_coord.top + window.innerHeight * 0.06            ) + 'px';          paddle_1_coord = paddle_1.getBoundingClientRect();        }          if (e.key == 'ArrowUp') {          paddle_2.style.top =            Math.max(              board_coord.top,              paddle_2_coord.top - window.innerHeight * 0.1            ) + 'px';          paddle_2_coord = paddle_2.getBoundingClientRect();        }        if (e.key == 'ArrowDown') {          paddle_2.style.top =            Math.min(              board_coord.bottom - paddle_common.height,              paddle_2_coord.top + window.innerHeight * 0.1            ) + 'px';          paddle_2_coord = paddle_2.getBoundingClientRect();        }      }    });      function moveBall(dx, dy, dxd, dyd) {      if (ball_coord.top <= board_coord.top) {        dyd = 1;      }      if (ball_coord.bottom >= board_coord.bottom) {        dyd = 0;      }      if (        ball_coord.left <= paddle_1_coord.right &&        ball_coord.top >= paddle_1_coord.top &&        ball_coord.bottom <= paddle_1_coord.bottom      ) {        dxd = 1;        dx = Math.floor(Math.random() * 4) + 3;        dy = Math.floor(Math.random() * 4) + 3;      }      if (        ball_coord.right >= paddle_2_coord.left &&        ball_coord.top >= paddle_2_coord.top &&        ball_coord.bottom <= paddle_2_coord.bottom      ) {        dxd = 0;        dx = Math.floor(Math.random() * 4) + 3;        dy = Math.floor(Math.random() * 4) + 3;      }      if (        ball_coord.left <= board_coord.left ||        ball_coord.right >= board_coord.right      ) {        if (ball_coord.left <= board_coord.left) {          score_2.innerHTML = +score_2.innerHTML + 1;        } else {          score_1.innerHTML = +score_1.innerHTML + 1;        }        gameState = 'start';          ball_coord = initial_ball_coord;        ball.style = initial_ball.style;        message.innerHTML = 'Press Enter to Play Pong';        message.style.left = 38 + 'vw';        return;      }      ball.style.top = ball_coord.top + dy * (dyd == 0 ? -1 : 1) + 'px';      ball.style.left = ball_coord.left + dx * (dxd == 0 ? -1 : 1) + 'px';      ball_coord = ball.getBoundingClientRect();      requestAnimationFrame(() => {        moveBall(dx, dy, dxd, dyd);      });    }  </script></body>    </html>
Output:
CSS-Questions
HTML-Questions
JavaScript-Questions
Technical Scripter 2020
CSS
HTML
JavaScript
Technical Scripter
Web Technologies
HTML
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Design a Tribute Page using HTML & CSS
How to set space between the flexbox ?
Build a Survey Form using HTML and CSS
Form validation using jQuery
Design a web page using HTML and CSS
REST API (Introduction)
Hide or show elements in HTML using display property
How to set the default value for an HTML <select> element ?
How to set input type date in dd-mm-yyyy format using HTML ?
HTTP headers | Content-Type