Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Raccoon Rumble</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> | |
/* Custom CSS */ | |
body { | |
overflow: hidden; | |
background-color: #1a202c; | |
font-family: 'Press Start 2P', cursive; | |
} | |
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); | |
#game-container { | |
position: relative; | |
width: 800px; | |
height: 400px; | |
margin: 0 auto; | |
background-image: url('https://images.unsplash.com/photo-1513828583688-c52646db42da?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80'); | |
background-size: cover; | |
overflow: hidden; | |
box-shadow: 0 0 20px rgba(0, 255, 255, 0.5); | |
border: 4px solid #4fd1c5; | |
border-radius: 10px; | |
} | |
.character { | |
position: absolute; | |
width: 100px; | |
height: 120px; | |
bottom: 0; | |
transition: transform 0.1s; | |
background-size: contain; | |
background-repeat: no-repeat; | |
background-position: bottom; | |
} | |
#player1 { | |
left: 100px; | |
background-image: url('https://i.imgur.com/JQZv0Qp.png'); | |
transform: scaleX(1); | |
} | |
#player2 { | |
right: 100px; | |
background-image: url('https://i.imgur.com/JQZv0Qp.png'); | |
transform: scaleX(-1); | |
filter: hue-rotate(180deg) brightness(1.2); | |
} | |
.health-bar { | |
height: 20px; | |
transition: width 0.3s; | |
border-radius: 5px; | |
box-shadow: 0 0 5px rgba(255, 255, 255, 0.5); | |
} | |
#player1-health { | |
background: linear-gradient(90deg, #3b82f6, #1d4ed8); | |
} | |
#player2-health { | |
background: linear-gradient(90deg, #ef4444, #b91c1c); | |
} | |
.attack-effect { | |
position: absolute; | |
width: 40px; | |
height: 40px; | |
background-color: rgba(255, 255, 0, 0.7); | |
border-radius: 50%; | |
animation: attack 0.3s forwards; | |
opacity: 0; | |
} | |
@keyframes attack { | |
0% { transform: scale(0.5); opacity: 0.7; } | |
100% { transform: scale(1.5); opacity: 0; } | |
} | |
.jump { | |
animation: jump 0.8s ease-out; | |
} | |
@keyframes jump { | |
0% { transform: translateY(0); } | |
50% { transform: translateY(-150px); } | |
100% { transform: translateY(0); } | |
} | |
.hit { | |
animation: hit 0.3s; | |
} | |
@keyframes hit { | |
0% { transform: translateX(0); } | |
25% { transform: translateX(10px); } | |
50% { transform: translateX(-10px); } | |
75% { transform: translateX(10px); } | |
100% { transform: translateX(0); } | |
} | |
#game-over { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(0, 0, 0, 0.8); | |
display: none; | |
justify-content: center; | |
align-items: center; | |
flex-direction: column; | |
z-index: 100; | |
} | |
.controls { | |
position: absolute; | |
bottom: 10px; | |
width: 100%; | |
text-align: center; | |
color: white; | |
font-size: 14px; | |
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); | |
} | |
.finisher-move { | |
position: absolute; | |
width: 200px; | |
height: 200px; | |
background-size: contain; | |
background-repeat: no-repeat; | |
background-position: center; | |
z-index: 50; | |
animation: finisher 1.5s forwards; | |
display: none; | |
} | |
@keyframes finisher { | |
0% { transform: scale(0.5); opacity: 0; } | |
20% { transform: scale(1.2); opacity: 1; } | |
80% { transform: scale(1.2); opacity: 1; } | |
100% { transform: scale(1.5); opacity: 0; } | |
} | |
.finisher-text { | |
position: absolute; | |
color: #fff; | |
font-size: 24px; | |
font-weight: bold; | |
text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #e60073; | |
z-index: 60; | |
animation: textPulse 1s infinite; | |
display: none; | |
} | |
@keyframes textPulse { | |
0% { transform: scale(1); } | |
50% { transform: scale(1.2); } | |
100% { transform: scale(1); } | |
} | |
.power-meter { | |
height: 10px; | |
background: linear-gradient(90deg, #f59e0b, #fbbf24); | |
border-radius: 5px; | |
transition: width 0.3s; | |
box-shadow: 0 0 5px rgba(245, 158, 11, 0.8); | |
} | |
.combo-counter { | |
position: absolute; | |
top: 10px; | |
right: 10px; | |
color: white; | |
font-size: 18px; | |
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); | |
display: none; | |
} | |
.combo-text { | |
animation: comboPulse 0.3s; | |
} | |
@keyframes comboPulse { | |
0% { transform: scale(1); } | |
50% { transform: scale(1.5); } | |
100% { transform: scale(1); } | |
} | |
</style> | |
</head> | |
<body class="bg-gray-900 text-white"> | |
<div class="container mx-auto py-8"> | |
<h1 class="text-4xl font-bold text-center mb-6 text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-red-500"> | |
<i class="fas fa-paw mr-2"></i>Raccoon Rumble<i class="fas fa-paw ml-2"></i> | |
</h1> | |
<div class="flex justify-between mb-4"> | |
<div class="w-1/2 pr-4"> | |
<h2 class="text-xl font-semibold mb-2 text-blue-400"> | |
<i class="fas fa-band-aid mr-2"></i>Blue Bandit | |
</h2> | |
<div class="health-container bg-gray-700 rounded h-6 mb-2"> | |
<div id="player1-health" class="health-bar" style="width: 100%"></div> | |
</div> | |
<div class="power-container bg-gray-800 rounded h-3 mb-2"> | |
<div id="player1-power" class="power-meter" style="width: 0%"></div> | |
</div> | |
<p class="text-sm text-blue-300"> | |
WASD: Move | Space: Attack | F: Finisher | |
</p> | |
</div> | |
<div class="w-1/2 pl-4"> | |
<h2 class="text-xl font-semibold mb-2 text-red-400"> | |
<i class="fas fa-band-aid mr-2"></i>Red Raider | |
</h2> | |
<div class="health-container bg-gray-700 rounded h-6 mb-2"> | |
<div id="player2-health" class="health-bar" style="width: 100%"></div> | |
</div> | |
<div class="power-container bg-gray-800 rounded h-3 mb-2"> | |
<div id="player2-power" class="power-meter" style="width: 0%"></div> | |
</div> | |
<p class="text-sm text-red-300"> | |
Arrows: Move | Enter: Attack | M: Finisher | |
</p> | |
</div> | |
</div> | |
<div id="game-container" class="relative"> | |
<div id="player1" class="character"></div> | |
<div id="player2" class="character"></div> | |
<div id="finisher-effect" class="finisher-move"></div> | |
<div id="finisher-text" class="finisher-text">FINISHER!</div> | |
<div id="player1-combo" class="combo-counter">Combo: 0</div> | |
<div id="player2-combo" class="combo-counter">Combo: 0</div> | |
<div id="game-over"> | |
<h2 id="winner-text" class="text-4xl font-bold mb-6 text-transparent bg-clip-text bg-gradient-to-r from-yellow-300 to-red-500"></h2> | |
<button id="restart-btn" class="px-6 py-3 bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 rounded-lg font-semibold shadow-lg transform transition hover:scale-105"> | |
<i class="fas fa-redo mr-2"></i>Play Again | |
</button> | |
</div> | |
<div class="controls"> | |
<p>First to reduce opponent's health to zero wins!</p> | |
<p>Build power meter to unleash FINISHER moves!</p> | |
</div> | |
</div> | |
<div class="mt-6 text-center text-gray-400 text-sm"> | |
<p>Special Moves: Press Attack + Down for a low attack</p> | |
<p>Finishers can only be used when power meter is full</p> | |
</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', () => { | |
// Game elements | |
const gameContainer = document.getElementById('game-container'); | |
const player1 = document.getElementById('player1'); | |
const player2 = document.getElementById('player2'); | |
const player1Health = document.getElementById('player1-health'); | |
const player2Health = document.getElementById('player2-health'); | |
const player1Power = document.getElementById('player1-power'); | |
const player2Power = document.getElementById('player2-power'); | |
const gameOverScreen = document.getElementById('game-over'); | |
const winnerText = document.getElementById('winner-text'); | |
const restartBtn = document.getElementById('restart-btn'); | |
const finisherEffect = document.getElementById('finisher-effect'); | |
const finisherText = document.getElementById('finisher-text'); | |
const player1Combo = document.getElementById('player1-combo'); | |
const player2Combo = document.getElementById('player2-combo'); | |
// Game state | |
const gameState = { | |
player1: { | |
x: 100, | |
y: 0, | |
width: 100, | |
height: 120, | |
speed: 5, | |
health: 100, | |
power: 0, | |
isJumping: false, | |
isAttacking: false, | |
isUsingFinisher: false, | |
direction: 'right', | |
comboCount: 0, | |
lastHitTime: 0 | |
}, | |
player2: { | |
x: gameContainer.offsetWidth - 200, | |
y: 0, | |
width: 100, | |
height: 120, | |
speed: 5, | |
health: 100, | |
power: 0, | |
isJumping: false, | |
isAttacking: false, | |
isUsingFinisher: false, | |
direction: 'left', | |
comboCount: 0, | |
lastHitTime: 0 | |
}, | |
gameRunning: true, | |
finisherActive: false | |
}; | |
// Key states | |
const keys = { | |
w: false, | |
a: false, | |
s: false, | |
d: false, | |
f: false, | |
space: false, | |
arrowup: false, | |
arrowleft: false, | |
arrowdown: false, | |
arrowright: false, | |
enter: false, | |
m: false | |
}; | |
// Event listeners for keyboard | |
document.addEventListener('keydown', (e) => { | |
if (!gameState.gameRunning) return; | |
switch(e.key.toLowerCase()) { | |
case 'w': keys.w = true; break; | |
case 'a': keys.a = true; break; | |
case 's': keys.s = true; break; | |
case 'd': keys.d = true; break; | |
case 'f': keys.f = true; break; | |
case ' ': keys.space = true; break; | |
case 'arrowup': keys.arrowup = true; break; | |
case 'arrowleft': keys.arrowleft = true; break; | |
case 'arrowdown': keys.arrowdown = true; break; | |
case 'arrowright': keys.arrowright = true; break; | |
case 'enter': keys.enter = true; break; | |
case 'm': keys.m = true; break; | |
} | |
}); | |
document.addEventListener('keyup', (e) => { | |
switch(e.key.toLowerCase()) { | |
case 'w': keys.w = false; break; | |
case 'a': keys.a = false; break; | |
case 's': keys.s = false; break; | |
case 'd': keys.d = false; break; | |
case 'f': keys.f = false; break; | |
case ' ': keys.space = false; break; | |
case 'arrowup': keys.arrowup = false; break; | |
case 'arrowleft': keys.arrowleft = false; break; | |
case 'arrowdown': keys.arrowdown = false; break; | |
case 'arrowright': keys.arrowright = false; break; | |
case 'enter': keys.enter = false; break; | |
case 'm': keys.m = false; break; | |
} | |
}); | |
// Restart game | |
restartBtn.addEventListener('click', () => { | |
gameState.player1.health = 100; | |
gameState.player2.health = 100; | |
gameState.player1.power = 0; | |
gameState.player2.power = 0; | |
gameState.player1.x = 100; | |
gameState.player2.x = gameContainer.offsetWidth - 200; | |
gameState.player1.isJumping = false; | |
gameState.player2.isJumping = false; | |
gameState.player1.isAttacking = false; | |
gameState.player2.isAttacking = false; | |
gameState.player1.isUsingFinisher = false; | |
gameState.player2.isUsingFinisher = false; | |
gameState.player1.comboCount = 0; | |
gameState.player2.comboCount = 0; | |
gameState.gameRunning = true; | |
gameState.finisherActive = false; | |
player1Health.style.width = '100%'; | |
player2Health.style.width = '100%'; | |
player1Power.style.width = '0%'; | |
player2Power.style.width = '0%'; | |
player1Combo.style.display = 'none'; | |
player2Combo.style.display = 'none'; | |
gameOverScreen.style.display = 'none'; | |
finisherEffect.style.display = 'none'; | |
finisherText.style.display = 'none'; | |
player1.style.transform = 'scaleX(1)'; | |
player2.style.transform = 'scaleX(-1)'; | |
}); | |
// Game loop | |
function gameLoop() { | |
if (!gameState.gameRunning) return; | |
// Player 1 movement | |
if (keys.a && gameState.player1.x > 0) { | |
gameState.player1.x -= gameState.player1.speed; | |
gameState.player1.direction = 'left'; | |
player1.style.transform = 'scaleX(1)'; | |
} | |
if (keys.d && gameState.player1.x < gameContainer.offsetWidth - gameState.player1.width) { | |
gameState.player1.x += gameState.player1.speed; | |
gameState.player1.direction = 'right'; | |
player1.style.transform = 'scaleX(-1)'; | |
} | |
if (keys.w && !gameState.player1.isJumping) { | |
gameState.player1.isJumping = true; | |
player1.classList.add('jump'); | |
setTimeout(() => { | |
player1.classList.remove('jump'); | |
gameState.player1.isJumping = false; | |
}, 800); | |
} | |
// Player 1 attack | |
if (keys.space && !gameState.player1.isAttacking && !gameState.player1.isUsingFinisher) { | |
gameState.player1.isAttacking = true; | |
const attackX = gameState.player1.direction === 'right' ? | |
gameState.player1.x + gameState.player1.width : | |
gameState.player1.x - 40; | |
createAttackEffect(attackX, gameState.player1.y + 40, gameState.player1.direction); | |
setTimeout(() => { | |
gameState.player1.isAttacking = false; | |
}, 300); | |
checkAttackHit('player1', keys.s ? 'low' : 'normal'); | |
} | |
// Player 1 finisher | |
if (keys.f && gameState.player1.power >= 100 && !gameState.finisherActive) { | |
gameState.player1.isUsingFinisher = true; | |
gameState.finisherActive = true; | |
gameState.player1.power = 0; | |
player1Power.style.width = '0%'; | |
// Show finisher effect | |
finisherEffect.style.backgroundImage = 'url("https://i.imgur.com/8KQn3kG.png")'; | |
finisherEffect.style.left = (gameState.player2.x - 50) + 'px'; | |
finisherEffect.style.top = (gameState.player2.y - 50) + 'px'; | |
finisherEffect.style.display = 'block'; | |
finisherText.style.left = (gameState.player2.x + 50) + 'px'; | |
finisherText.style.top = (gameState.player2.y - 80) + 'px'; | |
finisherText.style.display = 'block'; | |
setTimeout(() => { | |
finisherEffect.style.display = 'none'; | |
finisherText.style.display = 'none'; | |
gameState.player1.isUsingFinisher = false; | |
gameState.finisherActive = false; | |
}, 1500); | |
// Big damage | |
gameState.player2.health -= 30; | |
player2Health.style.width = `${gameState.player2.health}%`; | |
// Visual feedback for hit | |
player2.classList.add('hit'); | |
setTimeout(() => { | |
player2.classList.remove('hit'); | |
}, 300); | |
// Check if game over | |
if (gameState.player2.health <= 0) { | |
gameState.gameRunning = false; | |
gameOverScreen.style.display = 'flex'; | |
winnerText.textContent = `Blue Bandit Wins!`; | |
winnerText.innerHTML += '<br><span class="text-2xl">Finisher Move!</span>'; | |
} | |
} | |
// Player 2 movement | |
if (keys.arrowleft && gameState.player2.x > 0) { | |
gameState.player2.x -= gameState.player2.speed; | |
gameState.player2.direction = 'left'; | |
player2.style.transform = 'scaleX(-1)'; | |
} | |
if (keys.arrowright && gameState.player2.x < gameContainer.offsetWidth - gameState.player2.width) { | |
gameState.player2.x += gameState.player2.speed; | |
gameState.player2.direction = 'right'; | |
player2.style.transform = 'scaleX(1)'; | |
} | |
if (keys.arrowup && !gameState.player2.isJumping) { | |
gameState.player2.isJumping = true; | |
player2.classList.add('jump'); | |
setTimeout(() => { | |
player2.classList.remove('jump'); | |
gameState.player2.isJumping = false; | |
}, 800); | |
} | |
// Player 2 attack | |
if (keys.enter && !gameState.player2.isAttacking && !gameState.player2.isUsingFinisher) { | |
gameState.player2.isAttacking = true; | |
const attackX = gameState.player2.direction === 'right' ? | |
gameState.player2.x + gameState.player2.width : | |
gameState.player2.x - 40; | |
createAttackEffect(attackX, gameState.player2.y + 40, gameState.player2.direction); | |
setTimeout(() => { | |
gameState.player2.isAttacking = false; | |
}, 300); | |
checkAttackHit('player2', keys.arrowdown ? 'low' : 'normal'); | |
} | |
// Player 2 finisher | |
if (keys.m && gameState.player2.power >= 100 && !gameState.finisherActive) { | |
gameState.player2.isUsingFinisher = true; | |
gameState.finisherActive = true; | |
gameState.player2.power = 0; | |
player2Power.style.width = '0%'; | |
// Show finisher effect | |
finisherEffect.style.backgroundImage = 'url("https://i.imgur.com/8KQn3kG.png")'; | |
finisherEffect.style.filter = 'hue-rotate(180deg)'; | |
finisherEffect.style.left = (gameState.player1.x - 50) + 'px'; | |
finisherEffect.style.top = (gameState.player1.y - 50) + 'px'; | |
finisherEffect.style.display = 'block'; | |
finisherText.style.left = (gameState.player1.x + 50) + 'px'; | |
finisherText.style.top = (gameState.player1.y - 80) + 'px'; | |
finisherText.style.display = 'block'; | |
setTimeout(() => { | |
finisherEffect.style.display = 'none'; | |
finisherText.style.display = 'none'; | |
gameState.player2.isUsingFinisher = false; | |
gameState.finisherActive = false; | |
}, 1500); | |
// Big damage | |
gameState.player1.health -= 30; | |
player1Health.style.width = `${gameState.player1.health}%`; | |
// Visual feedback for hit | |
player1.classList.add('hit'); | |
setTimeout(() => { | |
player1.classList.remove('hit'); | |
}, 300); | |
// Check if game over | |
if (gameState.player1.health <= 0) { | |
gameState.gameRunning = false; | |
gameOverScreen.style.display = 'flex'; | |
winnerText.textContent = `Red Raider Wins!`; | |
winnerText.innerHTML += '<br><span class="text-2xl">Finisher Move!</span>'; | |
} | |
} | |
// Update positions | |
player1.style.left = gameState.player1.x + 'px'; | |
player2.style.left = gameState.player2.x + 'px'; | |
// Update combo counters | |
updateComboCounters(); | |
requestAnimationFrame(gameLoop); | |
} | |
// Create attack visual effect | |
function createAttackEffect(x, y, direction) { | |
const effect = document.createElement('div'); | |
effect.className = 'attack-effect'; | |
effect.style.left = x + 'px'; | |
effect.style.top = y + 'px'; | |
gameContainer.appendChild(effect); | |
setTimeout(() => { | |
effect.remove(); | |
}, 300); | |
} | |
// Check if attack hits opponent | |
function checkAttackHit(attacker, attackType) { | |
const attackerState = gameState[attacker]; | |
const defender = attacker === 'player1' ? 'player2' : 'player1'; | |
const defenderState = gameState[defender]; | |
const defenderElement = document.getElementById(defender); | |
// Simple collision detection | |
const attackRange = attackType === 'low' ? 60 : 50; | |
const attackerCenterX = attackerState.x + attackerState.width / 2; | |
const defenderCenterX = defenderState.x + defenderState.width / 2; | |
const distance = Math.abs(attackerCenterX - defenderCenterX); | |
if (distance < attackRange && (attackType === 'low' || !defenderState.isJumping)) { | |
// Hit successful | |
const damage = attackType === 'low' ? 8 : 10; | |
defenderState.health -= damage; | |
document.getElementById(`${defender}-health`).style.width = `${defenderState.health}%`; | |
// Add power to attacker | |
attackerState.power = Math.min(attackerState.power + 15, 100); | |
document.getElementById(`${attacker}-power`).style.width = `${attackerState.power}%`; | |
// Combo system | |
const now = Date.now(); | |
if (now - attackerState.lastHitTime < 1000) { | |
attackerState.comboCount++; | |
} else { | |
attackerState.comboCount = 1; | |
} | |
attackerState.lastHitTime = now; | |
// Update combo display | |
const comboElement = document.getElementById(`${attacker}-combo`); | |
comboElement.textContent = `Combo: ${attackerState.comboCount}`; | |
comboElement.style.display = 'block'; | |
comboElement.classList.add('combo-text'); | |
setTimeout(() => { | |
comboElement.classList.remove('combo-text'); | |
}, 300); | |
// Visual feedback for hit | |
defenderElement.classList.add('hit'); | |
setTimeout(() => { | |
defenderElement.classList.remove('hit'); | |
}, 300); | |
// Check if game over | |
if (defenderState.health <= 0) { | |
gameState.gameRunning = false; | |
gameOverScreen.style.display = 'flex'; | |
winnerText.textContent = `${attacker === 'player1' ? 'Blue Bandit' : 'Red Raider'} Wins!`; | |
} | |
} | |
} | |
// Update combo counters | |
function updateComboCounters() { | |
const now = Date.now(); | |
if (now - gameState.player1.lastHitTime > 2000 && gameState.player1.comboCount > 0) { | |
gameState.player1.comboCount = 0; | |
player1Combo.style.display = 'none'; | |
} | |
if (now - gameState.player2.lastHitTime > 2000 && gameState.player2.comboCount > 0) { | |
gameState.player2.comboCount = 0; | |
player2Combo.style.display = 'none'; | |
} | |
} | |
// Start the game | |
gameLoop(); | |
}); | |
</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=pijou/sharky-poop" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body> | |
</html> |