Ping Pong Game using React (original) (raw)

Last Updated : 23 Jul, 2024

Ping Pong is one of the earliest video games. It's a two-player game in which each player controls the paddle by dragging it from one side of the screen to the other to strike the ball back and forth. In this article, you will see how you can create a simple but exciting game of ping pong using React.

**Preview of the project: Let us have a look at how the final application will look like.ping

Prerequisites

Approach to create Ping Pong Game:

Steps to Create the Project:

**Step 1: Create a ReactJS project:

npx create-react-app ping-pong-game

**Step 2: Navigate to the project:

cd ping-pong-game

**Step 3: Start the project:

npm start

**Project Structure:

Screenshot-(1399)

The project structure of the code

The updated dependencies in package.json file will look like:

"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}

**Example : Write the following code in App.js file

CSS `

/App.css/

.ping-pong-container { position: relative; width: 600px; height: 400px; border: 1px solid #ccc; margin: 20px auto; overflow: hidden;

}

.paddle { position: absolute; width: 20px; height: 100px; background-color: #333; transition: top 0.2s; }

.paddle-left { left: 0; }

.paddle-right { right: 0; }

.ball { position: absolute; width: 20px; height: 20px; background-color: red; border-radius: 50%; transition: top 0.2s, left 0.2s; }

.paused { animation-play-state: paused; }

.controls { margin-top: 10px; display: flex; gap: 10px; }

button { padding: 5px 10px; font-size: 16px; cursor: pointer; }

.game-over { background-color: red; display: flex; justify-content: center; align-items: center; color: white; height: 45vh; }

` JavaScript ``

//App.js

import React, { useState, useEffect, useRef } from 'react'; import './App.css'; // Import the CSS file for styling

const App = () => { const initialBallState = { x: 300, y: 200, speedX: 5, speedY: 5 }; const initialPaddleState = { left: 150, right: 150 }; const [ball, setBall] = useState(initialBallState); const [paddles, setPaddles] = useState(initialPaddleState); const [gameOver, setGameOver] = useState(false); const [gameRunning, setGameRunning] = useState(false); const ballRef = useRef(null);

useEffect(() => { if (gameRunning) { const handleKeyPress = (e) => { switch (e.key) { case 'ArrowUp': setPaddles((prev) => ({ ...prev, right: Math.max(prev.right - 10, 0) })); break; case 'ArrowDown': setPaddles((prev) => ({ ...prev, right: Math.min(prev.right + 10, 300) })); break; case 'w': setPaddles((prev) => ({ ...prev, left: Math.max(prev.left - 10, 0) })); break; case 'd': setPaddles((prev) => ({ ...prev, left: Math.min(prev.left + 10, 300) })); break; default: break; } };

const updateGame = () => {
    setBall((prevBall) => ({
    ...prevBall,
    x: prevBall.x + prevBall.speedX,
    y: 200,
    }));

    const ballRect = ballRef.current.getBoundingClientRect();
    const paddleLeftRect = document.getElementById('paddle-left').getBoundingClientRect();
    const paddleRightRect = document.getElementById('paddle-right').getBoundingClientRect();

    // Check for collisions with paddles
    if (
    (ballRect.left <= paddleLeftRect.right &&
        ballRect.right >= paddleLeftRect.left &&
        ballRect.top <= paddleLeftRect.bottom &&
        ballRect.bottom >= paddleLeftRect.top) ||
    (ballRect.left <= paddleRightRect.right &&
        ballRect.right >= paddleRightRect.left &&
        ballRect.top <= paddleRightRect.bottom &&
        ballRect.bottom >= paddleRightRect.top)
    ) {
    setBall((prevBall) => ({ ...prevBall, speedX: -prevBall.speedX }));
    }

    // Check for collisions with top and bottom walls
    if (ball.y <= 0 || ball.y >= 380) {
    setBall((prevBall) => ({ ...prevBall, speedY: -prevBall.speedY }));
    }

    // Check for game over
    if (ball.x < 0 || ball.x > 600) {
    setGameOver(true);
    pauseGame();
    }
};
const intervalId = setInterval(updateGame, 50);

window.addEventListener('keydown', handleKeyPress);

return () => {
    clearInterval(intervalId);
    window.removeEventListener('keydown', handleKeyPress);
};
}

}, [gameRunning, ball]);

const startGame = () => { setGameRunning(true); };

const restartGame = () => { setBall(initialBallState); setPaddles(initialPaddleState); setGameOver(false); };

const pauseGame = () => { setGameRunning(false); };

return (

<div className={paddle paddle-left ${gameRunning ? '' : 'paused'}} id="paddle-left" style={{ top: ${paddles.left}px }} /> <div className={paddle paddle-right ${gameRunning ? '' : 'paused'}} id="paddle-right" style={{ top: ${paddles.right}px, left: '580px' }} /> <div className={ball ${gameRunning ? '' : 'paused'}} ref={ballRef} style={{ top: ${ball.y}px, left: ${ball.x}px }} />
Start Restart Pause
{gameOver &&
Game Over
}
); };

export default App;

``

**Output: