Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>8-Bit Bomb Defusal</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); | |
body { | |
font-family: 'Press Start 2P', cursive; | |
background-color: #1a1a2e; | |
overflow: hidden; | |
user-select: none; | |
} | |
.pixel { | |
image-rendering: pixelated; | |
image-rendering: -moz-crisp-edges; | |
image-rendering: crisp-edges; | |
} | |
.screen-shake { | |
animation: shake 0.1s infinite; | |
} | |
@keyframes shake { | |
0% { transform: translate(1px, 1px); } | |
10% { transform: translate(-1px, -2px); } | |
20% { transform: translate(-2px, 0px); } | |
30% { transform: translate(2px, 2px); } | |
40% { transform: translate(1px, -1px); } | |
50% { transform: translate(-1px, 2px); } | |
60% { transform: translate(-2px, 1px); } | |
70% { transform: translate(2px, 1px); } | |
80% { transform: translate(-1px, -1px); } | |
90% { transform: translate(1px, 2px); } | |
100% { transform: translate(0px, 0px); } | |
} | |
.wire-cut { | |
stroke-dasharray: 1000; | |
stroke-dashoffset: 1000; | |
animation: dash 0.5s linear forwards; | |
} | |
@keyframes dash { | |
to { | |
stroke-dashoffset: 0; | |
} | |
} | |
.explosion { | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
background: radial-gradient(circle, rgba(255,100,0,0.8) 0%, rgba(255,0,0,0.8) 70%, rgba(0,0,0,0.9) 100%); | |
z-index: 100; | |
opacity: 0; | |
pointer-events: none; | |
} | |
.success { | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
background: radial-gradient(circle, rgba(100,255,100,0.6) 0%, rgba(0,200,0,0.8) 70%, rgba(0,100,0,0.9) 100%); | |
z-index: 100; | |
opacity: 0; | |
pointer-events: none; | |
} | |
</style> | |
</head> | |
<body class="flex items-center justify-center h-screen"> | |
<div id="game-container" class="relative w-full max-w-md h-96 bg-gray-900 border-4 border-gray-700 rounded-lg overflow-hidden"> | |
<!-- Title Screen --> | |
<div id="title-screen" class="absolute inset-0 flex flex-col items-center justify-center bg-gray-900 z-50"> | |
<h1 class="text-3xl text-green-400 mb-8">BOMB DEFUSAL</h1> | |
<div class="text-yellow-300 text-center mb-8"> | |
<p class="mb-2">Cut the correct wire</p> | |
<p>before time runs out!</p> | |
</div> | |
<button id="start-btn" class="px-6 py-3 bg-red-500 text-white hover:bg-red-600 transition-all border-b-4 border-red-700 active:border-b-2 active:mt-1"> | |
START MISSION | |
</button> | |
<div class="absolute bottom-4 text-gray-500 text-xs"> | |
<p>Difficulty: HARD</p> | |
<p>Screen will shake!</p> | |
</div> | |
</div> | |
<!-- Game Screen --> | |
<div id="game-screen" class="absolute inset-0 hidden flex flex-col items-center justify-center"> | |
<div class="relative w-full h-full"> | |
<!-- Bomb --> | |
<div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"> | |
<div class="relative"> | |
<!-- Bomb body --> | |
<div class="w-24 h-32 bg-gray-800 rounded-full mx-auto border-4 border-gray-700"> | |
<div class="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-6 h-6 bg-red-600 rounded-full"></div> | |
<div class="absolute top-4 left-1/2 transform -translate-x-1/2 w-16 h-16 bg-gray-700 rounded-full flex items-center justify-center"> | |
<div class="w-12 h-12 bg-gray-800 rounded-full flex items-center justify-center"> | |
<div id="timer" class="text-red-500 text-xl">30</div> | |
</div> | |
</div> | |
</div> | |
<!-- Wires --> | |
<svg width="300" height="100" viewBox="0 0 300 100" class="absolute top-24 left-1/2 transform -translate-x-1/2"> | |
<!-- Wire 1 (Red) --> | |
<path id="wire1" d="M50,50 L150,50" stroke="red" stroke-width="4" stroke-linecap="round" class="cursor-pointer hover:stroke-yellow-300" /> | |
<circle cx="50" cy="50" r="8" fill="#333" /> | |
<circle cx="150" cy="50" r="8" fill="#333" /> | |
<!-- Wire 2 (Blue) --> | |
<path id="wire2" d="M50,50 L150,50" stroke="blue" stroke-width="4" stroke-linecap="round" class="cursor-pointer hover:stroke-yellow-300" /> | |
<circle cx="50" cy="50" r="8" fill="#333" /> | |
<circle cx="150" cy="50" r="8" fill="#333" /> | |
<!-- Wire 3 (Green) --> | |
<path id="wire3" d="M50,50 L150,50" stroke="green" stroke-width="4" stroke-linecap="round" class="cursor-pointer hover:stroke-yellow-300" /> | |
<circle cx="50" cy="50" r="8" fill="#333" /> | |
<circle cx="150" cy="50" r="8" fill="#333" /> | |
</svg> | |
<!-- Boxes --> | |
<div class="absolute top-32 left-1/2 transform -translate-x-1/2 flex space-x-16"> | |
<div class="w-16 h-16 bg-gray-700 border-2 border-gray-600 flex items-center justify-center"> | |
<div class="w-12 h-12 bg-gray-800"></div> | |
</div> | |
<div class="w-16 h-16 bg-gray-700 border-2 border-gray-600 flex items-center justify-center"> | |
<div class="w-12 h-12 bg-gray-800"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Timer bar --> | |
<div class="absolute bottom-4 left-1/2 transform -translate-x-1/2 w-64 h-4 bg-gray-800 border-2 border-gray-700"> | |
<div id="time-bar" class="h-full bg-red-500"></div> | |
</div> | |
</div> | |
</div> | |
<!-- Explosion effect --> | |
<div id="explosion" class="explosion"></div> | |
<!-- Success effect --> | |
<div id="success" class="success"></div> | |
<!-- Game Over Screen --> | |
<div id="game-over" class="absolute inset-0 hidden flex flex-col items-center justify-center bg-gray-900 bg-opacity-90 z-50"> | |
<h1 class="text-3xl text-red-500 mb-4">BOOM!</h1> | |
<p class="text-white mb-8">Mission failed</p> | |
<button id="retry-btn" class="px-6 py-3 bg-gray-700 text-white hover:bg-gray-600 transition-all border-b-4 border-gray-800 active:border-b-2 active:mt-1"> | |
TRY AGAIN | |
</button> | |
</div> | |
<!-- Success Screen --> | |
<div id="success-screen" class="absolute inset-0 hidden flex flex-col items-center justify-center bg-gray-900 bg-opacity-90 z-50"> | |
<h1 class="text-3xl text-green-400 mb-4">DEFUSED!</h1> | |
<p class="text-white mb-8">Mission accomplished</p> | |
<button id="next-btn" class="px-6 py-3 bg-green-600 text-white hover:bg-green-500 transition-all border-b-4 border-green-700 active:border-b-2 active:mt-1"> | |
NEXT BOMB | |
</button> | |
</div> | |
</div> | |
<audio id="tick-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-clock-countdown-bleeps-916.mp3" preload="auto"></audio> | |
<audio id="cut-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-retro-arcade-game-over-470.mp3" preload="auto"></audio> | |
<audio id="explosion-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-bomb-explosion-1700.mp3" preload="auto"></audio> | |
<audio id="success-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-achievement-bell-600.mp3" preload="auto"></audio> | |
<script> | |
// Game state | |
let gameActive = false; | |
let timeLeft = 30; | |
let timerInterval; | |
let correctWire; | |
let screenShakeInterval; | |
// DOM elements | |
const titleScreen = document.getElementById('title-screen'); | |
const gameScreen = document.getElementById('game-screen'); | |
const gameOverScreen = document.getElementById('game-over'); | |
const successScreen = document.getElementById('success-screen'); | |
const startBtn = document.getElementById('start-btn'); | |
const retryBtn = document.getElementById('retry-btn'); | |
const nextBtn = document.getElementById('next-btn'); | |
const timerDisplay = document.getElementById('timer'); | |
const timeBar = document.getElementById('time-bar'); | |
const wire1 = document.getElementById('wire1'); | |
const wire2 = document.getElementById('wire2'); | |
const wire3 = document.getElementById('wire3'); | |
const explosion = document.getElementById('explosion'); | |
const successEffect = document.getElementById('success'); | |
const gameContainer = document.getElementById('game-container'); | |
const tickSound = document.getElementById('tick-sound'); | |
const cutSound = document.getElementById('cut-sound'); | |
const explosionSound = document.getElementById('explosion-sound'); | |
const successSound = document.getElementById('success-sound'); | |
// Start game | |
startBtn.addEventListener('click', startGame); | |
retryBtn.addEventListener('click', startGame); | |
nextBtn.addEventListener('click', startGame); | |
function startGame() { | |
// Reset game state | |
gameActive = true; | |
timeLeft = 30; | |
correctWire = Math.floor(Math.random() * 3) + 1; // 1, 2, or 3 | |
// Show game screen | |
titleScreen.classList.add('hidden'); | |
gameOverScreen.classList.add('hidden'); | |
successScreen.classList.add('hidden'); | |
gameScreen.classList.remove('hidden'); | |
// Reset wires | |
wire1.classList.remove('wire-cut'); | |
wire2.classList.remove('wire-cut'); | |
wire3.classList.remove('wire-cut'); | |
wire1.style.display = ''; | |
wire2.style.display = ''; | |
wire3.style.display = ''; | |
// Reset effects | |
explosion.style.opacity = '0'; | |
successEffect.style.opacity = '0'; | |
// Start timer | |
clearInterval(timerInterval); | |
timerInterval = setInterval(updateTimer, 1000); | |
// Start screen shake | |
clearInterval(screenShakeInterval); | |
screenShakeInterval = setInterval(toggleShake, 100); | |
// Update display | |
timerDisplay.textContent = timeLeft; | |
timeBar.style.width = '100%'; | |
} | |
function toggleShake() { | |
if (gameActive) { | |
gameContainer.classList.toggle('screen-shake'); | |
} | |
} | |
function updateTimer() { | |
timeLeft--; | |
timerDisplay.textContent = timeLeft; | |
// Update timer bar | |
const percent = (timeLeft / 30) * 100; | |
timeBar.style.width = `${percent}%`; | |
// Play tick sound when time is running out | |
if (timeLeft <= 5 && timeLeft > 0) { | |
tickSound.currentTime = 0; | |
tickSound.play(); | |
} | |
// Change color when time is critical | |
if (timeLeft <= 10) { | |
timeBar.classList.remove('bg-red-500'); | |
timeBar.classList.add('bg-red-700'); | |
} | |
if (timeLeft <= 0) { | |
gameOver(); | |
} | |
} | |
// Wire click handlers | |
wire1.addEventListener('click', () => handleWireClick(1)); | |
wire2.addEventListener('click', () => handleWireClick(2)); | |
wire3.addEventListener('click', () => handleWireClick(3)); | |
function handleWireClick(wireNumber) { | |
if (!gameActive) return; | |
// Play cut sound | |
cutSound.currentTime = 0; | |
cutSound.play(); | |
// Animate wire cut | |
const wire = document.getElementById(`wire${wireNumber}`); | |
wire.classList.add('wire-cut'); | |
// Check if correct wire | |
if (wireNumber === correctWire) { | |
defuseSuccess(); | |
} else { | |
gameOver(); | |
} | |
// Disable further clicks | |
gameActive = false; | |
clearInterval(timerInterval); | |
clearInterval(screenShakeInterval); | |
gameContainer.classList.remove('screen-shake'); | |
} | |
function defuseSuccess() { | |
// Show success effect | |
successEffect.style.opacity = '1'; | |
// Play success sound | |
successSound.currentTime = 0; | |
successSound.play(); | |
// Show success screen after delay | |
setTimeout(() => { | |
gameScreen.classList.add('hidden'); | |
successScreen.classList.remove('hidden'); | |
}, 1500); | |
} | |
function gameOver() { | |
// Show explosion effect | |
explosion.style.opacity = '1'; | |
// Play explosion sound | |
explosionSound.currentTime = 0; | |
explosionSound.play(); | |
// Show game over screen after delay | |
setTimeout(() => { | |
gameScreen.classList.add('hidden'); | |
gameOverScreen.classList.remove('hidden'); | |
}, 1500); | |
} | |
</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=randt/bomb-defusal" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body> | |
</html> |