sharky-poop / index.html
pijou's picture
Add 1 files
8c6f446 verified
<!DOCTYPE html>
<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>