neon-pong-defender / index.html
gallabs's picture
Add 3 files
42f74c8 verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neon Pong Defender</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
body {
font-family: 'Orbitron', sans-serif;
background-color: #0f0f1a;
overflow: hidden;
margin: 0;
padding: 0;
cursor: none;
}
.game-container {
position: relative;
width: 800px;
height: 600px;
margin: 20px auto;
border: 3px solid #4f46e5;
border-radius: 8px;
box-shadow: 0 0 20px #4f46e5, inset 0 0 20px rgba(79, 70, 229, 0.3);
overflow: hidden;
}
.ball {
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
background: linear-gradient(145deg, #00ff9d, #00b8ff);
box-shadow: 0 0 10px #00ff9d, 0 0 20px #00b8ff;
transition: all 0.3s;
}
.paddle {
position: absolute;
width: 160px;
height: 15px;
bottom: 10px;
border-radius: 10px;
background: linear-gradient(145deg, #ff00aa, #ff0066);
box-shadow: 0 0 10px #ff00aa, 0 0 20px rgba(255, 0, 170, 0.5);
}
.score {
color: #00ff9d;
text-shadow: 0 0 5px #00ff9d;
font-size: 24px;
}
.timer {
color: #00b8ff;
text-shadow: 0 0 5px #00b8ff;
font-size: 24px;
}
.pulse {
animation: pulse 0.5s ease-out;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.3); }
100% { transform: scale(1); }
}
.explode {
animation: explode 0.5s ease-out;
}
@keyframes explode {
0% { transform: scale(1); opacity: 1; }
100% { transform: scale(3); opacity: 0; }
}
.grid-lines {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
linear-gradient(to right, rgba(79, 70, 229, 0.1) 1px, transparent 1px),
linear-gradient(to bottom, rgba(79, 70, 229, 0.1) 1px, transparent 1px);
background-size: 20px 20px;
pointer-events: none;
}
.game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(15, 15, 26, 0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
color: #ff0066;
font-size: 48px;
text-shadow: 0 0 10px #ff0066;
display: none;
}
.restart-btn {
margin-top: 20px;
padding: 10px 30px;
background: linear-gradient(145deg, #4f46e5, #7c3aed);
border: none;
border-radius: 5px;
color: white;
font-family: 'Orbitron', sans-serif;
font-size: 20px;
cursor: pointer;
box-shadow: 0 0 10px #4f46e5;
transition: all 0.3s;
}
.restart-btn:hover {
transform: scale(1.05);
box-shadow: 0 0 20px #4f46e5;
}
.speed-indicator {
position: absolute;
top: 10px;
right: 10px;
color: #00b8ff;
font-size: 16px;
text-shadow: 0 0 5px #00b8ff;
}
.particle {
position: absolute;
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #00ff9d;
pointer-events: none;
}
.custom-cursor {
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.5);
pointer-events: none;
z-index: 1000;
mix-blend-mode: difference;
display: none;
}
.controls-info {
position: absolute;
bottom: 40px;
left: 10px;
color: #4f46e5;
font-size: 12px;
text-shadow: 0 0 5px #4f46e5;
}
.instructions {
position: absolute;
top: 40px;
left: 10px;
color: #4f46e5;
font-size: 12px;
text-shadow: 0 0 5px #4f46e5;
background-color: rgba(15, 15, 26, 0.7);
padding: 10px;
border-radius: 5px;
max-width: 200px;
}
</style>
</head>
<body class="flex flex-col items-center justify-center min-h-screen">
<h1 class="text-4xl font-bold mb-4 text-transparent bg-clip-text bg-gradient-to-r from-purple-500 to-pink-500">NEON PONG DEFENDER</h1>
<div class="flex justify-between w-96 mb-4">
<div class="score">PONTOS: <span id="player-score">0</span></div>
<div class="timer">TEMPO: <span id="game-timer">00:00</span></div>
</div>
<div class="game-container" id="game-container">
<div class="grid-lines"></div>
<div class="speed-indicator">VELOCIDADE: <span id="speed-level">1x</span></div>
<div class="ball" id="ball"></div>
<div class="paddle" id="paddle"></div>
<div class="game-over" id="game-over">
FIM DE JOGO
<button class="restart-btn" id="restart-btn">JOGAR NOVAMENTE</button>
</div>
<div class="controls-info">CONTROLES: Teclas de seta ou mouse</div>
<div class="instructions">
<p><strong>COMO JOGAR:</strong></p>
<p>- Use as teclas ← → ou o mouse para mover a raquete</p>
<p>- Impedir que a bola caia</p>
<p>- Cada rebatida marca 1 ponto</p>
<p>- A velocidade aumenta a cada minuto</p>
</div>
</div>
<div class="mt-4 text-purple-400 text-center">
<p>Defenda a bola com sua raquete e marque o máximo de pontos!</p>
<p class="text-sm text-purple-600">O jogo fica mais rápido a cada minuto!</p>
</div>
<div class="custom-cursor" id="custom-cursor"></div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const gameContainer = document.getElementById('game-container');
const ball = document.getElementById('ball');
const paddle = document.getElementById('paddle');
const playerScoreElement = document.getElementById('player-score');
const gameTimerElement = document.getElementById('game-timer');
const gameOverScreen = document.getElementById('game-over');
const restartBtn = document.getElementById('restart-btn');
const speedLevelElement = document.getElementById('speed-level');
const customCursor = document.getElementById('custom-cursor');
const containerWidth = gameContainer.offsetWidth;
const containerHeight = gameContainer.offsetHeight;
const paddleWidth = containerWidth / 5;
let ballX = containerWidth / 2;
let ballY = 50;
let ballSpeedX = 3;
let ballSpeedY = 3;
let paddleX = (containerWidth - paddleWidth) / 2;
let playerScore = 0;
let gameTime = 0;
let gameSpeed = 1;
let gameRunning = true;
let animationId;
let mouseX = 0;
let useMouse = false;
// Cores aleatórias para a bola
const ballColors = [
{gradient: 'linear-gradient(145deg, #00ff9d, #00b8ff)', shadow1: '#00ff9d', shadow2: '#00b8ff'},
{gradient: 'linear-gradient(145deg, #ff9d00, #ff00b8)', shadow1: '#ff9d00', shadow2: '#ff00b8'},
{gradient: 'linear-gradient(145deg, #9d00ff, #00b8ff)', shadow1: '#9d00ff', shadow2: '#00b8ff'},
{gradient: 'linear-gradient(145deg, #ff0066, #ffcc00)', shadow1: '#ff0066', shadow2: '#ffcc00'},
{gradient: 'linear-gradient(145deg, #00ff66, #6600ff)', shadow1: '#00ff66', shadow2: '#6600ff'}
];
// Set initial paddle size
paddle.style.width = `${paddleWidth}px`;
// Mouse movement tracking
gameContainer.addEventListener('mousemove', (e) => {
const rect = gameContainer.getBoundingClientRect();
mouseX = e.clientX - rect.left - paddleWidth / 2;
useMouse = true;
// Update custom cursor position
customCursor.style.display = 'block';
customCursor.style.left = `${e.clientX - 10}px`;
customCursor.style.top = `${e.clientY - 10}px`;
});
gameContainer.addEventListener('mouseleave', () => {
useMouse = false;
customCursor.style.display = 'none';
});
// Keyboard controls
const keys = {
ArrowLeft: false,
ArrowRight: false
};
document.addEventListener('keydown', (e) => {
if (e.key in keys) {
keys[e.key] = true;
useMouse = false;
customCursor.style.display = 'none';
}
});
document.addEventListener('keyup', (e) => {
if (e.key in keys) {
keys[e.key] = false;
}
});
restartBtn.addEventListener('click', resetGame);
function updatePaddlePosition() {
if (useMouse) {
// Mouse control
paddleX = Math.max(0, Math.min(mouseX, containerWidth - paddleWidth));
} else {
// Keyboard control
if (keys.ArrowLeft && paddleX > 0) {
paddleX -= 8 * gameSpeed;
}
if (keys.ArrowRight && paddleX < containerWidth - paddleWidth) {
paddleX += 8 * gameSpeed;
}
}
paddle.style.left = `${paddleX}px`;
}
function updateBallPosition() {
ballX += ballSpeedX * gameSpeed;
ballY += ballSpeedY * gameSpeed;
// Ball collision with walls
if (ballX <= 0) {
ballX = 0;
ballSpeedX = -ballSpeedX;
createParticles(ballX, ballY, 5);
}
if (ballX >= containerWidth - 20) {
ballX = containerWidth - 20;
ballSpeedX = -ballSpeedX;
createParticles(ballX, ballY, 5);
}
// Ball collision with ceiling
if (ballY <= 0) {
ballY = 0;
ballSpeedY = -ballSpeedY;
createParticles(ballX, ballY, 5);
}
// Ball collision with paddle
if (
ballY >= containerHeight - 35 &&
ballY <= containerHeight - 20 &&
ballX >= paddleX &&
ballX <= paddleX + paddleWidth
) {
ballSpeedY = -ballSpeedY;
// Add some randomness to the bounce
const hitPosition = (ballX - paddleX) / paddleWidth;
ballSpeedX = (hitPosition - 0.5) * 8;
playerScore++;
playerScoreElement.textContent = playerScore;
// Paddle hit effect
paddle.classList.add('pulse');
setTimeout(() => paddle.classList.remove('pulse'), 500);
// Explode current ball and create new one
ball.classList.add('explode');
createParticles(ballX, ballY, 20, '#ff00aa');
// Create new ball with random color
setTimeout(() => {
ball.classList.remove('explode');
const randomColor = ballColors[Math.floor(Math.random() * ballColors.length)];
ball.style.background = randomColor.gradient;
ball.style.boxShadow = `0 0 10px ${randomColor.shadow1}, 0 0 20px ${randomColor.shadow2}`;
ballX = containerWidth / 2;
ballY = 50;
ballSpeedX = (Math.random() > 0.5 ? 3 : -3) * gameSpeed;
ballSpeedY = 3 * gameSpeed;
}, 500);
}
// Ball out of bounds (game over)
if (ballY >= containerHeight) {
gameOver();
// Explosion effect
ball.classList.add('explode');
createParticles(ballX, ballY, 20, '#ff0066');
}
ball.style.left = `${ballX}px`;
ball.style.top = `${ballY}px`;
}
function createParticles(x, y, count, color = '#00ff9d') {
for (let i = 0; i < count; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
particle.style.left = `${x}px`;
particle.style.top = `${y}px`;
particle.style.backgroundColor = color;
gameContainer.appendChild(particle);
const angle = Math.random() * Math.PI * 2;
const speed = 1 + Math.random() * 3;
const lifetime = 500 + Math.random() * 500;
const particleSpeedX = Math.cos(angle) * speed;
const particleSpeedY = Math.sin(angle) * speed;
let particleX = x;
let particleY = y;
const animateParticle = () => {
particleX += particleSpeedX;
particleY += particleSpeedY;
particle.style.opacity = parseFloat(particle.style.opacity || 1) - 0.01;
particle.style.left = `${particleX}px`;
particle.style.top = `${particleY}px`;
if (parseFloat(particle.style.opacity || 1) > 0) {
requestAnimationFrame(animateParticle);
} else {
particle.remove();
}
};
setTimeout(() => {
animateParticle();
}, 10);
setTimeout(() => {
particle.remove();
}, lifetime);
}
}
function updateTimer() {
gameTime++;
const minutes = Math.floor(gameTime / 60).toString().padStart(2, '0');
const seconds = (gameTime % 60).toString().padStart(2, '0');
gameTimerElement.textContent = `${minutes}:${seconds}`;
// Increase game speed every minute
if (gameTime % 60 === 0) {
gameSpeed += 0.25;
speedLevelElement.textContent = `${gameSpeed.toFixed(2)}x`;
// Speed increase effect
gameContainer.style.boxShadow = `0 0 30px #4f46e5, inset 0 0 30px rgba(79, 70, 229, 0.5)`;
setTimeout(() => {
gameContainer.style.boxShadow = `0 0 20px #4f46e5, inset 0 0 20px rgba(79, 70, 229, 0.3)`;
}, 500);
}
}
function gameOver() {
gameRunning = false;
gameOverScreen.style.display = 'flex';
cancelAnimationFrame(animationId);
}
function resetGame() {
ballX = containerWidth / 2;
ballY = 50;
ballSpeedX = 3;
ballSpeedY = 3;
paddleX = (containerWidth - paddleWidth) / 2;
playerScore = 0;
gameTime = 0;
gameSpeed = 1;
// Reset ball color
ball.style.background = 'linear-gradient(145deg, #00ff9d, #00b8ff)';
ball.style.boxShadow = '0 0 10px #00ff9d, 0 0 20px #00b8ff';
playerScoreElement.textContent = '0';
gameTimerElement.textContent = '00:00';
speedLevelElement.textContent = '1x';
ball.classList.remove('explode');
gameOverScreen.style.display = 'none';
gameRunning = true;
// Remove all particles
document.querySelectorAll('.particle').forEach(p => p.remove());
gameLoop();
}
function gameLoop() {
if (!gameRunning) return;
updatePaddlePosition();
updateBallPosition();
animationId = requestAnimationFrame(gameLoop);
}
// Start the game
resetGame();
// Start timer
setInterval(() => {
if (gameRunning) {
updateTimer();
}
}, 1000);
});
</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=gallabs/neon-pong-defender" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>