“🅱️ong” is an enhanced version of the classic Pong arcade game featuring timed gameplay, dynamic paddle controls, and administrative override capabilities. The game includes a 90-second countdown timer, horizontal paddle movement mechanics, and Firebase integration for remote management, creating a modern twist on the timeless two-player competitive experience.
pong/
└── index.html # Complete Pong game with Firebase integration (320 lines)
#pong {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000; /* Classic black playing field */
}
.paddle {
position: absolute;
width: 20px;
height: 100px;
background-color: #fff; /* White paddles */
}
.ball {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
border-radius: 50%; /* Circular ball */
}
#scores {
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
color: #fff;
font-size: 24px;
font-family: "Helvetica", Arial, sans-serif;
font-weight: bold;
}
#countdown {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
color: #fff;
font-size: 20px;
font-family: "Helvetica", Arial, sans-serif;
}
let ballSpeed = 12; /* Initial ball speed */
let ballXSpeed = ballSpeed; /* Horizontal velocity */
let ballYSpeed = ballSpeed; /* Vertical velocity */
function moveBall() {
ballXPosition += ballXSpeed;
ballYPosition += ballYSpeed;
// Wall collision detection
if (ballYPosition <= 0 || ballYPosition >= pong.offsetHeight - ball.offsetHeight) {
ballYSpeed *= -1; /* Reverse vertical direction */
}
// Paddle collision detection
if (collision(leftPaddle, ball) || collision(rightPaddle, ball)) {
// Position adjustment for accurate collision
if (ballXSpeed > 0) {
ballXPosition = rightPaddle.offsetLeft - ball.offsetWidth;
} else {
ballXPosition = leftPaddle.offsetLeft + leftPaddle.offsetWidth;
}
ballXSpeed *= -1; /* Reverse horizontal direction */
}
}
function collision(paddle, ball) {
const paddleRect = paddle.getBoundingClientRect();
const ballRect = ball.getBoundingClientRect();
return (
paddleRect.bottom > ballRect.top &&
paddleRect.top < ballRect.bottom &&
paddleRect.right > ballRect.left &&
paddleRect.left < ballRect.right
);
}
const paddleSpeed = 10; /* Vertical movement speed */
const paddleXSpeed = 5; /* Horizontal movement speed */
function movePaddles() {
// Left paddle controls (W/S for vertical, A/D for horizontal)
if (keysDown.w) {
paddleLeftPosition -= paddleSpeed;
}
if (keysDown.s) {
paddleLeftPosition += paddleSpeed;
}
// Horizontal movement only after countdown ends
if (secondsLeft <= 0) {
if (keysDown.a) {
paddleLeftXPosition -= paddleXSpeed;
}
if (keysDown.d) {
paddleLeftXPosition += paddleXSpeed;
}
}
// Right paddle controls (Arrow keys)
if (keysDown.ArrowUp) {
paddleRightPosition -= paddleSpeed;
}
if (keysDown.ArrowDown) {
paddleRightPosition += paddleSpeed;
}
// Horizontal movement only after countdown ends
if (secondsLeft <= 0) {
if (keysDown.ArrowLeft) {
paddleRightXPosition -= paddleXSpeed;
}
if (keysDown.ArrowRight) {
paddleRightXPosition += paddleXSpeed;
}
}
}
// Restrict paddle movement within game area
paddleLeftPosition = Math.max(Math.min(paddleLeftPosition, pong.offsetHeight - leftPaddle.offsetHeight), 0);
paddleLeftXPosition = Math.max(Math.min(paddleLeftXPosition, pong.offsetWidth - leftPaddle.offsetWidth), 0);
paddleRightPosition = Math.max(Math.min(paddleRightPosition, pong.offsetHeight - rightPaddle.offsetHeight), 0);
paddleRightXPosition = Math.max(Math.min(paddleRightXPosition, pong.offsetWidth - rightPaddle.offsetWidth), 0);
const gameDuration = 90; /* Game duration in seconds */
let secondsLeft = gameDuration;
let gameStarted = false;
let countdownInterval;
function startGame() {
if (!gameStarted) {
countdownInterval = setInterval(updateCountdown, 1000);
gameStarted = true;
}
}
function updateCountdown() {
secondsLeft--;
if (secondsLeft <= 0) {
clearInterval(countdownInterval);
gameStarted = true;
ballSpeed = 8; /* Reduce ball speed after countdown */
enablePaddleControl();
requestAnimationFrame(update);
}
// Format time display (MM:SS)
const minutes = Math.floor(secondsLeft / 60);
const seconds = secondsLeft % 60;
countdownDisplay.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
const keysDown = {};
window.addEventListener('keydown', function (event) {
keysDown[event.key] = true;
});
window.addEventListener('keyup', function (event) {
keysDown[event.key] = false;
});
Left Player Controls:
Right Player Controls:
// Check if ball is out of bounds
if (ballXPosition <= 0) {
// Right player scores
rightScore++;
resetBall();
} else if (ballXPosition >= pong.offsetWidth - ball.offsetWidth) {
// Left player scores
leftScore++;
resetBall();
}
// Update score display
leftScoreDisplay.textContent = leftScore;
rightScoreDisplay.textContent = rightScore;
function resetBall() {
ballXPosition = pong.offsetWidth / 2 - ball.offsetWidth / 2;
ballYPosition = pong.offsetHeight / 2 - ball.offsetHeight / 2;
ballSpeed = Math.random() > 0.5 ? -ballSpeed : ballSpeed; /* Random direction */
ballXSpeed = ballSpeed;
ballYSpeed = ballSpeed;
}
function update() {
if (gameStarted) {
movePaddles();
moveBall();
}
requestAnimationFrame(update); /* Smooth 60fps animation */
}
// Initialize game loop
update();
setTimeout(startGame, 2500); /* Start game after 2.5 seconds */
const switchFirebaseConfig = {
apiKey: "AIzaSyCRPBjKJfKoLO52TqROpQ3I9X-nEL-0btE",
databaseURL: "https://joshbruceonline-switch-default-rtdb.europe-west1.firebasedatabase.app/",
authDomain: "joshbruceonline-switch.firebaseapp.com",
projectId: "joshbruceonline-switch",
storageBucket: "joshbruceonline-switch.appspot.com",
messagingSenderId: "592073701037",
appId: "1:592073701037:web:309eb7bed49885153a7824"
};
const switchApp = firebase.initializeApp(switchFirebaseConfig, 'switch');
const switchDb = switchApp.database();
const switchPageRef = switchDb.ref('pong');
const redirectLinkRef = switchDb.ref('redirectLink');
switchPageRef.on('value', (snapshot) => {
const isPageActive = snapshot.val();
if (isPageActive === false) {
// Get redirect destination
redirectLinkRef.once('value', (snapshot) => {
const redirectLink = snapshot.val();
if (redirectLink) {
// Redirect to specified URL
window.location.href = redirectLink;
} else {
// Default redirect to backrooms
window.location.href = 'https://joshbruce.online/backrooms';
}
});
}
});
// Initial fast ball speed
ballSpeed = 12;
// Reduced speed after countdown for better gameplay
if (secondsLeft <= 0) {
ballSpeed = 8;
}
// Clean interval management
function startGame() {
if (!gameStarted) {
countdownInterval = setInterval(updateCountdown, 1000);
gameStarted = true;
}
}
// Proper cleanup when countdown ends
if (secondsLeft <= 0) {
clearInterval(countdownInterval);
}
🅱️ong represents an excellent enhancement of the classic Pong arcade game, successfully combining nostalgic gameplay with modern web technologies. The timed gameplay mechanics, enhanced paddle controls, and Firebase administrative features create an engaging and manageable gaming experience.
Technical Rating: 8.4/10
The application successfully demonstrates how classic arcade games can be enhanced with modern web technologies while maintaining their essential gameplay characteristics and nostalgic appeal.