Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Pixel Arcade - Retro Gaming</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); | |
body { | |
font-family: 'Press Start 2P', cursive; | |
background-color: #0f0f1a; | |
color: #e0e0e0; | |
overflow-x: hidden; | |
} | |
.pixel-border { | |
border: 4px solid #ff00ff; | |
box-shadow: | |
0 0 0 4px #00ffff, | |
0 0 0 8px #ff00ff, | |
0 0 0 12px #ffff00; | |
} | |
.pixel-text { | |
text-shadow: 4px 4px 0px #ff00ff, -4px -4px 0px #00ffff; | |
} | |
.scanlines { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: linear-gradient( | |
rgba(18, 16, 16, 0) 50%, | |
rgba(0, 0, 0, 0.25) 50% | |
); | |
background-size: 100% 4px; | |
pointer-events: none; | |
z-index: 100; | |
} | |
.game-screen { | |
background: repeating-linear-gradient( | |
0deg, | |
rgba(0, 0, 0, 0.15), | |
rgba(0, 0, 0, 0.15) 1px, | |
transparent 1px, | |
transparent 2px | |
); | |
} | |
.pixel-btn { | |
position: relative; | |
transition: all 0.2s; | |
} | |
.pixel-btn:hover { | |
transform: translate(-2px, -2px); | |
box-shadow: 4px 4px 0px #ff00ff; | |
} | |
.pixel-btn:active { | |
transform: translate(0, 0); | |
box-shadow: none; | |
} | |
@keyframes blink { | |
0%, 100% { opacity: 1; } | |
50% { opacity: 0.5; } | |
} | |
.blink { | |
animation: blink 1s infinite; | |
} | |
/* Game canvases */ | |
#snake-game, #tetris-game, #pong-game { | |
border: 4px solid #00ff00; | |
image-rendering: pixelated; | |
} | |
#tetris-game { border-color: #ff00ff; } | |
#pong-game { border-color: #ffff00; } | |
/* CRT TV effect */ | |
.crt-effect::before { | |
content: " "; | |
display: block; | |
position: absolute; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
right: 0; | |
background: rgba(18, 16, 16, 0.1); | |
opacity: 0.15; | |
z-index: 2; | |
pointer-events: none; | |
} | |
.crt-effect::after { | |
content: " "; | |
display: block; | |
position: absolute; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
right: 0; | |
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06)); | |
z-index: 2; | |
background-size: 100% 2px, 3px 100%; | |
pointer-events: none; | |
} | |
/* Tetris blocks */ | |
.tetris-I { background-color: #00FFFF; } | |
.tetris-J { background-color: #0000FF; } | |
.tetris-L { background-color: #FF7F00; } | |
.tetris-O { background-color: #FFFF00; } | |
.tetris-S { background-color: #00FF00; } | |
.tetris-T { background-color: #800080; } | |
.tetris-Z { background-color: #FF0000; } | |
</style> | |
</head> | |
<body class="min-h-screen"> | |
<!-- CRT Scanlines Effect --> | |
<div class="scanlines"></div> | |
<!-- Main Container --> | |
<div class="container mx-auto px-4 py-8 crt-effect"> | |
<!-- Header --> | |
<header class="text-center mb-12"> | |
<h1 class="text-5xl md:text-6xl lg:text-7xl mb-6 text-purple-400 pixel-text">PIXEL ARCADE</h1> | |
<p class="text-lg text-cyan-300 mb-8">RETRO GAMING EXPERIENCE</p> | |
<div class="flex justify-center space-x-4 mb-8"> | |
<button class="pixel-btn bg-purple-600 text-white px-6 py-3 rounded-none">PLAY NOW</button> | |
<button class="pixel-btn bg-cyan-600 text-white px-6 py-3 rounded-none">HIGH SCORES</button> | |
<button class="pixel-btn bg-yellow-600 text-white px-6 py-3 rounded-none">ABOUT</button> | |
</div> | |
<div class="flex justify-center"> | |
<div class="pixel-border p-4 inline-block"> | |
<div class="bg-black p-2 game-screen"> | |
<p class="text-green-400 blink">INSERT COIN</p> | |
</div> | |
</div> | |
</div> | |
</header> | |
<!-- Featured Games --> | |
<section class="mb-16"> | |
<h2 class="text-3xl text-yellow-400 mb-8 text-center pixel-text">CLASSIC GAMES</h2> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-8"> | |
<!-- Snake Game --> | |
<div class="pixel-border p-4 bg-gray-900"> | |
<h3 class="text-xl text-green-400 mb-4">SNAKE</h3> | |
<div class="relative"> | |
<canvas id="snake-game" width="300" height="300" class="w-full bg-black"></canvas> | |
<div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 p-2"> | |
<p class="text-xs text-white">Arrow keys to move</p> | |
</div> | |
</div> | |
<button onclick="startSnakeGame()" class="pixel-btn bg-green-600 text-white px-4 py-2 mt-4 w-full">PLAY SNAKE</button> | |
</div> | |
<!-- Tetris Game --> | |
<div class="pixel-border p-4 bg-gray-900"> | |
<h3 class="text-xl text-purple-400 mb-4">TETRIS</h3> | |
<div class="relative"> | |
<canvas id="tetris-game" width="300" height="480" class="w-full bg-black"></canvas> | |
<div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 p-2"> | |
<p class="text-xs text-white">Arrow keys to move, Up to rotate</p> | |
</div> | |
</div> | |
<button onclick="startTetrisGame()" class="pixel-btn bg-purple-600 text-white px-4 py-2 mt-4 w-full">PLAY TETRIS</button> | |
</div> | |
<!-- Pong Game --> | |
<div class="pixel-border p-4 bg-gray-900"> | |
<h3 class="text-xl text-yellow-400 mb-4">PONG</h3> | |
<div class="relative"> | |
<canvas id="pong-game" width="300" height="400" class="w-full bg-black"></canvas> | |
<div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 p-2"> | |
<p class="text-xs text-white">W/S keys for left paddle</p> | |
<p class="text-xs text-white">Up/Down for right paddle</p> | |
</div> | |
</div> | |
<button onclick="startPongGame()" class="pixel-btn bg-yellow-600 text-white px-4 py-2 mt-4 w-full">PLAY PONG</button> | |
</div> | |
</div> | |
</section> | |
<!-- Retro Consoles --> | |
<section class="mb-16"> | |
<h2 class="text-3xl text-cyan-400 mb-8 text-center pixel-text">RETRO CONSOLES</h2> | |
<div class="grid grid-cols-2 md:grid-cols-4 gap-6"> | |
<div class="text-center"> | |
<div class="pixel-border p-2 bg-gray-800 mb-2"> | |
<i class="fas fa-gamepad text-4xl text-red-500"></i> | |
</div> | |
<p class="text-sm">NES</p> | |
</div> | |
<div class="text-center"> | |
<div class="pixel-border p-2 bg-gray-800 mb-2"> | |
<i class="fas fa-gamepad text-4xl text-blue-500"></i> | |
</div> | |
<p class="text-sm">SNES</p> | |
</div> | |
<div class="text-center"> | |
<div class="pixel-border p-2 bg-gray-800 mb-2"> | |
<i class="fas fa-gamepad text-4xl text-green-500"></i> | |
</div> | |
<p class="text-sm">SEGA</p> | |
</div> | |
<div class="text-center"> | |
<div class="pixel-border p-2 bg-gray-800 mb-2"> | |
<i class="fas fa-gamepad text-4xl text-yellow-500"></i> | |
</div> | |
<p class="text-sm">ATARI</p> | |
</div> | |
</div> | |
</section> | |
<!-- Footer --> | |
<footer class="text-center py-8 border-t border-purple-900"> | |
<div class="flex justify-center space-x-6 mb-4"> | |
<a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-twitter"></i></a> | |
<a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-facebook"></i></a> | |
<a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-instagram"></i></a> | |
<a href="#" class="text-purple-400 hover:text-cyan-400"><i class="fab fa-discord"></i></a> | |
</div> | |
<p class="text-xs text-gray-500">© 2023 PIXEL ARCADE - ALL RIGHTS RESERVED</p> | |
<p class="text-xs text-gray-600 mt-2">CREATED WITH <i class="fas fa-heart text-red-500"></i> FOR RETRO GAMERS</p> | |
</footer> | |
</div> | |
<script> | |
// ========== SNAKE GAME ========== | |
let snakeGame; | |
let snakeCtx; | |
let snake = []; | |
let food = {}; | |
let direction = 'right'; | |
let snakeLoop; | |
let snakeScore = 0; | |
function startSnakeGame() { | |
snakeGame = document.getElementById('snake-game'); | |
snakeCtx = snakeGame.getContext('2d'); | |
// Initialize snake | |
snake = [ | |
{x: 150, y: 150}, | |
{x: 140, y: 150}, | |
{x: 130, y: 150}, | |
{x: 120, y: 150}, | |
{x: 110, y: 150} | |
]; | |
// Create first food | |
createSnakeFood(); | |
// Reset score | |
snakeScore = 0; | |
// Start game loop | |
if (snakeLoop) clearInterval(snakeLoop); | |
snakeLoop = setInterval(updateSnakeGame, 100); | |
// Focus on canvas for keyboard controls | |
snakeGame.focus(); | |
} | |
function createSnakeFood() { | |
food = { | |
x: Math.floor(Math.random() * 30) * 10, | |
y: Math.floor(Math.random() * 30) * 10 | |
}; | |
// Make sure food doesn't appear on snake | |
for (let segment of snake) { | |
if (segment.x === food.x && segment.y === food.y) { | |
return createSnakeFood(); | |
} | |
} | |
} | |
function updateSnakeGame() { | |
// Move snake | |
let head = {x: snake[0].x, y: snake[0].y}; | |
switch(direction) { | |
case 'up': head.y -= 10; break; | |
case 'down': head.y += 10; break; | |
case 'left': head.x -= 10; break; | |
case 'right': head.x += 10; break; | |
} | |
// Check collision with walls | |
if (head.x < 0 || head.x >= snakeGame.width || head.y < 0 || head.y >= snakeGame.height) { | |
clearInterval(snakeLoop); | |
alert('Game Over! Score: ' + snakeScore); | |
return; | |
} | |
// Check collision with self | |
for (let segment of snake) { | |
if (segment.x === head.x && segment.y === head.y) { | |
clearInterval(snakeLoop); | |
alert('Game Over! Score: ' + snakeScore); | |
return; | |
} | |
} | |
// Check if snake ate food | |
if (head.x === food.x && head.y === food.y) { | |
snakeScore += 10; | |
createSnakeFood(); | |
} else { | |
snake.pop(); // Remove tail if no food eaten | |
} | |
snake.unshift(head); // Add new head | |
// Draw everything | |
snakeCtx.fillStyle = 'black'; | |
snakeCtx.fillRect(0, 0, snakeGame.width, snakeGame.height); | |
// Draw snake | |
snakeCtx.fillStyle = 'lime'; | |
for (let segment of snake) { | |
snakeCtx.fillRect(segment.x, segment.y, 10, 10); | |
} | |
// Draw food | |
snakeCtx.fillStyle = 'red'; | |
snakeCtx.fillRect(food.x, food.y, 10, 10); | |
// Draw score | |
snakeCtx.fillStyle = 'white'; | |
snakeCtx.font = '20px "Press Start 2P"'; | |
snakeCtx.fillText('Score: ' + snakeScore, 10, 25); | |
} | |
// Keyboard controls for snake | |
document.getElementById('snake-game').addEventListener('keydown', function(e) { | |
switch(e.key) { | |
case 'ArrowUp': if (direction !== 'down') direction = 'up'; break; | |
case 'ArrowDown': if (direction !== 'up') direction = 'down'; break; | |
case 'ArrowLeft': if (direction !== 'right') direction = 'left'; break; | |
case 'ArrowRight': if (direction !== 'left') direction = 'right'; break; | |
} | |
}); | |
// ========== TETRIS GAME ========== | |
let tetrisGame; | |
let tetrisCtx; | |
let tetrisBoard = []; | |
let currentPiece; | |
let nextPiece; | |
let tetrisScore = 0; | |
let tetrisLoop; | |
let dropCounter = 0; | |
let dropInterval = 1000; | |
let lastTime = 0; | |
const COLS = 10; | |
const ROWS = 20; | |
const BLOCK_SIZE = 30; | |
// Tetris pieces | |
const PIECES = [ | |
{ shape: [[1,1,1,1]], color: 'tetris-I' }, // I | |
{ shape: [[1,0,0],[1,1,1]], color: 'tetris-J' }, // J | |
{ shape: [[0,0,1],[1,1,1]], color: 'tetris-L' }, // L | |
{ shape: [[1,1],[1,1]], color: 'tetris-O' }, // O | |
{ shape: [[0,1,1],[1,1,0]], color: 'tetris-S' }, // S | |
{ shape: [[0,1,0],[1,1,1]], color: 'tetris-T' }, // T | |
{ shape: [[1,1,0],[0,1,1]], color: 'tetris-Z' } // Z | |
]; | |
function startTetrisGame() { | |
tetrisGame = document.getElementById('tetris-game'); | |
tetrisCtx = tetrisGame.getContext('2d'); | |
tetrisGame.width = COLS * BLOCK_SIZE; | |
tetrisGame.height = ROWS * BLOCK_SIZE; | |
// Scale canvas for display | |
tetrisGame.style.width = '300px'; | |
tetrisGame.style.height = '480px'; | |
// Initialize empty board | |
createBoard(); | |
// Create first piece | |
currentPiece = createPiece(); | |
nextPiece = createPiece(); | |
// Reset score | |
tetrisScore = 0; | |
// Start game loop | |
if (tetrisLoop) cancelAnimationFrame(tetrisLoop); | |
lastTime = 0; | |
tetrisLoop = requestAnimationFrame(updateTetrisGame); | |
// Focus on canvas for keyboard controls | |
tetrisGame.focus(); | |
} | |
function createBoard() { | |
tetrisBoard = Array.from(Array(ROWS), () => Array(COLS).fill(0)); | |
} | |
function createPiece() { | |
const piece = JSON.parse(JSON.stringify(PIECES[Math.floor(Math.random() * PIECES.length)])); | |
piece.pos = {x: Math.floor(COLS/2) - 1, y: -2}; | |
return piece; | |
} | |
function updateTetrisGame(time = 0) { | |
const deltaTime = time - lastTime; | |
lastTime = time; | |
dropCounter += deltaTime; | |
if (dropCounter > dropInterval) { | |
movePieceDown(); | |
dropCounter = 0; | |
} | |
drawTetrisGame(); | |
tetrisLoop = requestAnimationFrame(updateTetrisGame); | |
} | |
function drawTetrisGame() { | |
tetrisCtx.fillStyle = 'black'; | |
tetrisCtx.fillRect(0, 0, tetrisGame.width, tetrisGame.height); | |
// Draw board | |
drawBoard(); | |
// Draw current piece | |
drawPiece(); | |
// Draw score | |
tetrisCtx.fillStyle = 'white'; | |
tetrisCtx.font = '18px "Press Start 2P"'; | |
tetrisCtx.fillText('Score: ' + tetrisScore, 10, 25); | |
} | |
function drawBoard() { | |
tetrisBoard.forEach((row, y) => { | |
row.forEach((value, x) => { | |
if (value) { | |
tetrisCtx.fillStyle = PIECES[value-1].color; | |
tetrisCtx.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); | |
tetrisCtx.strokeStyle = 'black'; | |
tetrisCtx.strokeRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); | |
} | |
}); | |
}); | |
} | |
function drawPiece() { | |
currentPiece.shape.forEach((row, y) => { | |
row.forEach((value, x) => { | |
if (value) { | |
tetrisCtx.fillStyle = currentPiece.color; | |
tetrisCtx.fillRect( | |
(currentPiece.pos.x + x) * BLOCK_SIZE, | |
(currentPiece.pos.y + y) * BLOCK_SIZE, | |
BLOCK_SIZE, | |
BLOCK_SIZE | |
); | |
tetrisCtx.strokeStyle = 'black'; | |
tetrisCtx.strokeRect( | |
(currentPiece.pos.x + x) * BLOCK_SIZE, | |
(currentPiece.pos.y + y) * BLOCK_SIZE, | |
BLOCK_SIZE, | |
BLOCK_SIZE | |
); | |
} | |
}); | |
}); | |
} | |
function movePieceDown() { | |
currentPiece.pos.y++; | |
if (collision()) { | |
currentPiece.pos.y--; | |
mergePiece(); | |
removeRows(); | |
currentPiece = nextPiece; | |
nextPiece = createPiece(); | |
// Check game over | |
if (collision()) { | |
cancelAnimationFrame(tetrisLoop); | |
alert('Game Over! Score: ' + tetrisScore); | |
return; | |
} | |
} | |
dropCounter = 0; | |
} | |
function collision() { | |
return currentPiece.shape.some((row, y) => { | |
return row.some((value, x) => { | |
return value && | |
(currentPiece.pos.x + x < 0 || | |
currentPiece.pos.x + x >= COLS || | |
currentPiece.pos.y + y >= ROWS || | |
tetrisBoard[currentPiece.pos.y + y][currentPiece.pos.x + x]); | |
}); | |
}); | |
} | |
function mergePiece() { | |
currentPiece.shape.forEach((row, y) => { | |
row.forEach((value, x) => { | |
if (value) { | |
tetrisBoard[currentPiece.pos.y + y][currentPiece.pos.x + x] = | |
PIECES.findIndex(p => p.color === currentPiece.color) + 1; | |
} | |
}); | |
}); | |
} | |
function removeRows() { | |
let rowsCleared = 0; | |
outer: for (let y = ROWS - 1; y >= 0; y--) { | |
for (let x = 0; x < COLS; x++) { | |
if (tetrisBoard[y][x] === 0) { | |
continue outer; | |
} | |
} | |
// Remove the row | |
const row = tetrisBoard.splice(y, 1)[0].fill(0); | |
tetrisBoard.unshift(row); | |
y++; // Check the same row again (the row moved down) | |
rowsCleared++; | |
} | |
// Update score | |
if (rowsCleared > 0) { | |
tetrisScore += [100, 300, 500, 800][rowsCleared - 1] || 0; | |
dropInterval *= 0.9; // Increase speed | |
} | |
} | |
function rotatePiece() { | |
const originalShape = currentPiece.shape; | |
// Transpose and reverse rows = rotation | |
currentPiece.shape = currentPiece.shape[0].map((_, index) => | |
currentPiece.shape.map(row => row[index]).reverse() | |
); | |
if (collision()) { | |
currentPiece.shape = originalShape; | |
} | |
} | |
// Keyboard controls for Tetris | |
document.getElementById('tetris-game').addEventListener('keydown', function(e) { | |
if (e.key === 'ArrowLeft') { | |
currentPiece.pos.x--; | |
if (collision()) currentPiece.pos.x++; | |
} else if (e.key === 'ArrowRight') { | |
currentPiece.pos.x++; | |
if (collision()) currentPiece.pos.x--; | |
} else if (e.key === 'ArrowDown') { | |
movePieceDown(); | |
} else if (e.key === 'ArrowUp') { | |
rotatePiece(); | |
} | |
}); | |
// ========== PONG GAME ========== | |
let pongGame; | |
let pongCtx; | |
let pongLoop; | |
let leftPaddle = { y: 150, width: 10, height: 80 }; | |
let rightPaddle = { y: 150, width: 10, height: 80 }; | |
let ball = { x: 150, y: 200, radius: 8, dx: 4, dy: 4 }; | |
let playerScore = 0; | |
let computerScore = 0; | |
const PADDLE_SPEED = 6; | |
function startPongGame() { | |
pongGame = document.getElementById('pong-game'); | |
pongCtx = pongGame.getContext('2d'); | |
pongGame.width = 300; | |
pongGame.height = 400; | |
// Reset positions | |
leftPaddle = { y: 150, width: 10, height: 80 }; | |
rightPaddle = { y: 150, width: 10, height: 80 }; | |
ball = { x: 150, y: 200, radius: 8, dx: 4, dy: 4 }; | |
playerScore = 0; | |
computerScore = 0; | |
// Start game loop | |
if (pongLoop) cancelAnimationFrame(pongLoop); | |
pongLoop = requestAnimationFrame(updatePongGame); | |
// Focus on canvas for keyboard controls | |
pongGame.focus(); | |
} | |
function updatePongGame() { | |
// Move ball | |
ball.x += ball.dx; | |
ball.y += ball.dy; | |
// Simple AI for right paddle | |
if (rightPaddle.y + rightPaddle.height/2 < ball.y) { | |
rightPaddle.y += PADDLE_SPEED - 1; | |
} else { | |
rightPaddle.y -= PADDLE_SPEED - 1; | |
} | |
// Wall collision (top/bottom) | |
if (ball.y - ball.radius < 0 || ball.y + ball.radius > pongGame.height) { | |
ball.dy = -ball.dy; | |
} | |
// Paddle collision | |
// Left paddle | |
if ( | |
ball.dx < 0 && | |
ball.x - ball.radius < leftPaddle.width && | |
ball.y > leftPaddle.y && | |
ball.y < leftPaddle.y + leftPaddle.height | |
) { | |
ball.dx = -ball.dx; | |
// Add angle based on where ball hits paddle | |
const hitPos = (ball.y - (leftPaddle.y + leftPaddle.height/2)) / (leftPaddle.height/2); | |
ball.dy = hitPos * 5; | |
} | |
// Right paddle | |
if ( | |
ball.dx > 0 && | |
ball.x + ball.radius > pongGame.width - rightPaddle.width && | |
ball.y > rightPaddle.y && | |
ball.y < rightPaddle.y + rightPaddle.height | |
) { | |
ball.dx = -ball.dx; | |
// Add angle based on where ball hits paddle | |
const hitPos = (ball.y - (rightPaddle.y + rightPaddle.height/2)) / (rightPaddle.height/2); | |
ball.dy = hitPos * 5; | |
} | |
// Score points | |
if (ball.x - ball.radius < 0) { | |
computerScore++; | |
resetBall(); | |
} else if (ball.x + ball.radius > pongGame.width) { | |
playerScore++; | |
resetBall(); | |
} | |
// Game over (first to 5 points) | |
if (playerScore >= 5 || computerScore >= 5) { | |
cancelAnimationFrame(pongLoop); | |
const winner = playerScore >= 5 ? "PLAYER" : "COMPUTER"; | |
alert(`${winner} WINS! Final Score: ${playerScore}-${computerScore}`); | |
return; | |
} | |
drawPongGame(); | |
pongLoop = requestAnimationFrame(updatePongGame); | |
} | |
function resetBall() { | |
ball.x = pongGame.width / 2; | |
ball.y = pongGame.height / 2; | |
ball.dx = -ball.dx; | |
ball.dy = Math.random() * 4 - 2; | |
} | |
function drawPongGame() { | |
// Draw background | |
pongCtx.fillStyle = 'black'; | |
pongCtx.fillRect(0, 0, pongGame.width, pongGame.height); | |
// Draw center line | |
pongCtx.strokeStyle = '#333'; | |
pongCtx.setLineDash([10, 10]); | |
pongCtx.beginPath(); | |
pongCtx.moveTo(pongGame.width/2, 0); | |
pongCtx.lineTo(pongGame.width/2, pongGame.height); | |
pongCtx.stroke(); | |
pongCtx.setLineDash([]); | |
// Draw paddles | |
pongCtx.fillStyle = 'cyan'; | |
pongCtx.fillRect(0, leftPaddle.y, leftPaddle.width, leftPaddle.height); | |
pongCtx.fillRect(pongGame.width - rightPaddle.width, rightPaddle.y, rightPaddle.width, rightPaddle.height); | |
// Draw ball | |
pongCtx.fillStyle = 'white'; | |
pongCtx.beginPath(); | |
pongCtx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2); | |
pongCtx.fill(); | |
// Draw scores | |
pongCtx.fillStyle = 'white'; | |
pongCtx.font = '24px "Press Start 2P"'; | |
pongCtx.textAlign = 'center'; | |
pongCtx.fillText(playerScore, pongGame.width / 4, 40); | |
pongCtx.fillText(computerScore, (pongGame.width / 4) * 3, 40); | |
} | |
// Keyboard controls for Pong | |
document.addEventListener('keydown', (e) => { | |
switch(e.key) { | |
case 'w': | |
case 'W': | |
if (leftPaddle.y > 0) leftPaddle.y -= PADDLE_SPEED; | |
break; | |
case 's': | |
case 'S': | |
if (leftPaddle.y < pongGame.height - leftPaddle.height) leftPaddle.y += PADDLE_SPEED; | |
break; | |
case 'ArrowUp': | |
if (rightPaddle.y > 0) rightPaddle.y -= PADDLE_SPEED; | |
break; | |
case 'ArrowDown': | |
if (rightPaddle.y < pongGame.height - rightPaddle.height) rightPaddle.y += PADDLE_SPEED; | |
break; | |
} | |
}); | |
// Make canvases focusable | |
document.getElementById('snake-game').tabIndex = 0; | |
document.getElementById('tetris-game').tabIndex = 0; | |
document.getElementById('pong-game').tabIndex = 0; | |
// Start snake game by default | |
window.onload = function() { | |
startSnakeGame(); | |
}; | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=saishshinde15/classic-games" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body> | |
</html> |