tiod2 / index.html
tapitordie's picture
Add 1 files
8048c45 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TAP IT OR DIE!</title>
<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');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Press Start 2P', cursive;
background-color: #121212;
color: #00ff00;
text-align: center;
overflow: hidden;
height: 100vh;
-webkit-tap-highlight-color: transparent;
}
#game-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
position: relative;
padding: 20px;
}
#start-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
gap: 30px;
text-shadow: 0 0 10px #00ff00;
}
#game-title {
font-size: 3rem;
margin-bottom: 20px;
color: #ff0;
text-shadow: 0 0 10px #ff0, 0 0 20px #ff0;
animation: pulse 1.5s infinite alternate;
}
#game-over-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
gap: 30px;
}
#game-over-content {
position: relative;
z-index: 101;
display: flex;
flex-direction: column;
align-items: center;
gap: 30px;
}
button {
background: #00ff00;
color: #000;
border: none;
padding: 15px 30px;
font-family: 'Press Start 2P', cursive;
font-size: 1.2rem;
cursor: pointer;
border-radius: 5px;
transition: all 0.3s;
box-shadow: 0 0 10px #00ff00;
position: relative;
z-index: 101;
}
button:hover {
background: #ff0;
transform: scale(1.05);
box-shadow: 0 0 20px #ff0;
}
.game-info {
display: flex;
justify-content: space-between;
width: 100%;
max-width: 600px;
margin-bottom: 20px;
font-size: 1rem;
position: relative;
z-index: 10;
}
#game-board {
width: 100%;
max-width: 600px;
height: 400px;
border: 8px solid #333;
position: relative;
background-color: #000;
overflow: hidden;
box-shadow: inset 0 0 20px #000, 0 0 30px #00ff00;
}
.explosion {
position: absolute;
width: 60px;
height: 60px;
background-image: radial-gradient(circle, #ff0, #f80, #f00);
border-radius: 50%;
pointer-events: none;
transform: scale(0);
animation: explode 0.5s forwards;
z-index: 10;
}
.bomb {
position: absolute;
width: 40px;
height: 40px;
background-color: #333;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: transform 0.2s;
box-shadow: inset 0 0 10px #111, 0 0 10px #f00;
animation: bomb-pulse 1s infinite alternate;
z-index: 5;
}
.bomb::before {
content: "";
position: absolute;
width: 10px;
height: 10px;
background-color: #f00;
border-radius: 50%;
box-shadow: 0 0 10px #f00;
}
.bomb:hover {
transform: scale(1.1);
}
.bomb.ready {
background-color: #f00;
animation: danger-pulse 0.5s infinite alternate;
}
.bomb.ready::before {
background-color: #ff0;
}
.bomb-bonus {
background-color: #0af;
box-shadow: inset 0 0 10px #111, 0 0 10px #0af;
}
.bomb-bonus::before {
background-color: #fff;
}
#countdown {
font-size: 2rem;
margin: 20px 0;
text-shadow: 0 0 10px #00ff00;
position: relative;
z-index: 10;
}
#difficulty-selector {
margin: 20px 0;
display: flex;
gap: 10px;
position: relative;
z-index: 10;
flex-wrap: wrap;
justify-content: center;
}
#difficulty-selector button {
font-size: 0.8rem;
padding: 10px 15px;
}
#difficulty-selector button.active {
background: #ff0;
box-shadow: 0 0 15px #ff0;
}
#game-over-difficulty {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
margin-top: 20px;
}
#game-over-difficulty h3 {
color: #ff0;
margin-bottom: 10px;
font-size: 1rem;
}
.scanlines {
position: absolute;
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: 5;
}
@keyframes pulse {
0% { transform: scale(1); }
100% { transform: scale(1.05); }
}
@keyframes bomb-pulse {
0% { box-shadow: inset 0 0 10px #111, 0 0 5px #f00; }
100% { box-shadow: inset 0 0 10px #111, 0 0 15px #f00; }
}
@keyframes danger-pulse {
0% { box-shadow: inset 0 0 10px #111, 0 0 5px #f00; transform: scale(1); }
100% { box-shadow: inset 0 0 10px #111, 0 0 20px #f00; transform: scale(1.1); }
}
@keyframes explode {
0% { transform: scale(0); opacity: 1; }
100% { transform: scale(4); opacity: 0; }
}
.leaderboard {
position: absolute;
right: 20px;
top: 20px;
background: rgba(0, 0, 0, 0.8);
border: 2px solid #00ff00;
padding: 10px;
max-height: 200px;
overflow-y: auto;
display: none;
z-index: 10;
}
.leaderboard h3 {
margin-bottom: 10px;
color: #ff0;
}
.leaderboard-entry {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-size: 0.8rem;
}
.danger {
animation: danger-flash 0.2s infinite;
}
@keyframes danger-flash {
0%, 100% { background-color: #121212; }
50% { background-color: #330000; }
}
.game-over-explosion {
position: absolute;
width: 120px;
height: 120px;
background-image: radial-gradient(circle, #ff0, #f80, #f00);
border-radius: 50%;
pointer-events: none;
transform: scale(0);
animation: final-explode 1s forwards;
z-index: 100;
}
@keyframes final-explode {
0% { transform: scale(0); opacity: 1; }
100% { transform: scale(10); opacity: 0; }
}
.shake {
animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both;
}
@keyframes shake {
10%, 90% { transform: translate3d(-1px, 0, 0); }
20%, 80% { transform: translate3d(2px, 0, 0); }
30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
40%, 60% { transform: translate3d(4px, 0, 0); }
}
@media (max-width: 600px) {
#game-title {
font-size: 1.8rem;
}
button {
padding: 10px 20px;
font-size: 0.9rem;
}
.game-info {
font-size: 0.7rem;
}
#game-board {
height: 300px;
}
.bomb {
width: 30px;
height: 30px;
}
.leaderboard {
position: static;
margin-top: 20px;
width: 100%;
max-height: 100px;
}
#difficulty-selector button {
font-size: 0.7rem;
padding: 8px 12px;
}
#game-over-content {
gap: 20px;
}
}
</style>
</head>
<body>
<div id="game-container">
<div id="start-screen">
<h1 id="game-title">TAP IT OR DIE!</h1>
<p>Defuse the bombs before they explode!</p>
<p id="high-score-display">HIGH SCORE: 0</p>
<div id="difficulty-selector">
<button class="active" data-difficulty="easy">EASY</button>
<button data-difficulty="medium">MEDIUM</button>
<button data-difficulty="hard">HARD</button>
<button data-difficulty="insane">INSANE</button>
</div>
<button id="start-button">
<i class="fas fa-bomb"></i> START GAME <i class="fas fa-bomb"></i>
</button>
</div>
<div id="game-over-screen">
<div id="game-over-content">
<h1>GAME OVER!</h1>
<p>BOOM! You got exploded.</p>
<p id="final-score">SCORE: 0</p>
<div id="game-over-difficulty">
<h3>SELECT DIFFICULTY</h3>
<div id="difficulty-selector-game-over">
<button class="active" data-difficulty="easy">EASY</button>
<button data-difficulty="medium">MEDIUM</button>
<button data-difficulty="hard">HARD</button>
<button data-difficulty="insane">INSANE</button>
</div>
</div>
<button id="restart-button">TRY AGAIN</button>
</div>
</div>
<div class="game-info">
<div>SCORE: <span id="score">0</span></div>
<div>LIVES: <span id="lives">3</span></div>
</div>
<div id="countdown">GET READY!</div>
<div id="game-board">
<div class="scanlines"></div>
</div>
<div class="leaderboard">
<h3>TOP SCORES</h3>
<div id="leaderboard-entries"></div>
</div>
</div>
<script>
// Game variables
let score = 0;
let lives = 3;
let gameActive = false;
let gameTimer;
let bombCount = 0;
let difficulty = 'medium';
let highScore = localStorage.getItem('highScore') || 0;
let leaderboard = JSON.parse(localStorage.getItem('leaderboard')) || [];
// DOM elements
const gameContainer = document.getElementById('game-container');
const gameBoard = document.getElementById('game-board');
const scoreDisplay = document.getElementById('score');
const livesDisplay = document.getElementById('lives');
const startScreen = document.getElementById('start-screen');
const gameOverScreen = document.getElementById('game-over-screen');
const gameOverContent = document.getElementById('game-over-content');
const startButton = document.getElementById('start-button');
const restartButton = document.getElementById('restart-button');
const difficultyButtons = document.querySelectorAll('[data-difficulty]');
const difficultyButtonsGameOver = document.querySelectorAll('#difficulty-selector-game-over [data-difficulty]');
const countdownDisplay = document.getElementById('countdown');
const highScoreDisplay = document.getElementById('high-score-display');
const finalScoreDisplay = document.getElementById('final-score');
const leaderboardElement = document.querySelector('.leaderboard');
const leaderboardEntries = document.getElementById('leaderboard-entries');
// Initialize game
window.onload = function() {
updateHighScoreDisplay();
updateLeaderboardDisplay();
// Event listeners
startButton.addEventListener('click', startGame);
restartButton.addEventListener('click', restartGame);
// Main difficulty selector
difficultyButtons.forEach(button => {
button.addEventListener('click', function() {
setDifficulty(this.dataset.difficulty);
difficultyButtons.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
});
});
// Game over screen difficulty selector
difficultyButtonsGameOver.forEach(button => {
button.addEventListener('click', function() {
setDifficulty(this.dataset.difficulty);
difficultyButtonsGameOver.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
});
});
// Show leaderboard on hover of high score
highScoreDisplay.addEventListener('mouseenter', () => {
leaderboardElement.style.display = 'block';
});
highScoreDisplay.addEventListener('mouseleave', () => {
leaderboardElement.style.display = 'none';
});
};
function setDifficulty(newDifficulty) {
difficulty = newDifficulty;
// Update both selectors to show current difficulty
difficultyButtons.forEach(btn => {
btn.classList.remove('active');
if(btn.dataset.difficulty === difficulty) btn.classList.add('active');
});
difficultyButtonsGameOver.forEach(btn => {
btn.classList.remove('active');
if(btn.dataset.difficulty === difficulty) btn.classList.add('active');
});
}
function startGame() {
startScreen.style.display = 'none';
gameActive = true;
score = 0;
lives = 3;
bombCount = 0;
// Reset UI
scoreDisplay.textContent = score;
livesDisplay.textContent = lives;
document.body.classList.remove('danger');
gameOverScreen.style.display = 'none';
// Clear any existing bombs
gameBoard.querySelectorAll('.bomb').forEach(bomb => bomb.remove());
// Start countdown
let countdown = 3;
countdownDisplay.style.display = 'block';
const countdownInterval = setInterval(() => {
countdownDisplay.textContent = countdown > 0 ? countdown : 'GO!';
if (countdown <= 0) {
clearInterval(countdownInterval);
countdownDisplay.style.display = 'none';
startBombTimer();
}
countdown--;
}, 1000);
}
function startBombTimer() {
// Set bomb spawn interval based on difficulty
let spawnInterval;
let bombLifeTime;
switch(difficulty) {
case 'easy':
spawnInterval = 1500;
bombLifeTime = 4000;
break;
case 'medium':
spawnInterval = 1000;
bombLifeTime = 3000;
break;
case 'hard':
spawnInterval = 650;
bombLifeTime = 2000;
break;
case 'insane':
spawnInterval = 400;
bombLifeTime = 1500;
break;
}
gameTimer = setInterval(() => {
if (!gameActive) return;
createBomb(bombLifeTime);
bombCount++;
// Increase difficulty over time
if (bombCount % 10 === 0 && spawnInterval > 300) {
spawnInterval -= 100;
bombLifeTime = Math.max(bombLifeTime - 200, 1000);
clearInterval(gameTimer);
gameTimer = setInterval(arguments.callee, spawnInterval);
}
}, spawnInterval);
}
function createBomb(lifetime) {
const bomb = document.createElement('div');
bomb.className = 'bomb';
// 5% chance for a bonus bomb
if (Math.random() < 0.05) {
bomb.classList.add('bomb-bonus');
}
// Size variation
const size = 30 + Math.floor(Math.random() * 30);
bomb.style.width = `${size}px`;
bomb.style.height = `${size}px`;
// Position randomly on the game board
const maxX = gameBoard.offsetWidth - size;
const maxY = gameBoard.offsetHeight - size;
const x = Math.floor(Math.random() * maxX);
const y = Math.floor(Math.random() * maxY);
bomb.style.left = `${x}px`;
bomb.style.top = `${y}px`;
// Add click event to defuse the bomb
bomb.addEventListener('click', function() {
defuseBomb(this);
});
gameBoard.appendChild(bomb);
// Bomb becomes ready after short delay
setTimeout(() => {
bomb.classList.add('ready');
}, Math.random() * 1000);
// Bomb explodes after lifetime
const explodeTimer = setTimeout(() => {
if (bomb.parentNode === gameBoard) {
explodeBomb(bomb);
}
}, lifetime);
// Store timer on bomb for cleanup
bomb.dataset.timer = explodeTimer;
}
function defuseBomb(bomb) {
if (!bomb.classList.contains('ready')) return;
clearTimeout(bomb.dataset.timer);
// Check if it's a bonus bomb
const isBonus = bomb.classList.contains('bomb-bonus');
// Calculate points based on how quickly it was tapped
let points = isBonus ? 50 : 10;
// Add extra points for quick defuse
if (isBonus) {
points += Math.floor(Math.random() * 50);
} else {
points += Math.floor(Math.random() * 20);
}
score += points;
scoreDisplay.textContent = score;
createExplosion(bomb, isBonus ? '#0af' : '#00ff00');
bomb.remove();
}
function explodeBomb(bomb) {
if (!gameActive) return;
lives--;
livesDisplay.textContent = lives;
// Visual feedback when low on lives
if (lives === 1) {
document.body.classList.add('danger');
}
// Screen shake effect
gameContainer.classList.add('shake');
setTimeout(() => {
gameContainer.classList.remove('shake');
}, 500);
createExplosion(bomb, '#ff0000');
bomb.remove();
if (lives <= 0) {
endGame();
}
}
function createExplosion(element, color) {
const rect = element.getBoundingClientRect();
const gameRect = gameBoard.getBoundingClientRect();
const x = rect.left - gameRect.left + rect.width / 2;
const y = rect.top - gameRect.top + rect.height / 2;
const explosion = document.createElement('div');
explosion.className = 'explosion';
explosion.style.left = `${x - 30}px`;
explosion.style.top = `${y - 30}px`;
explosion.style.background = color;
gameBoard.appendChild(explosion);
// Remove explosion after animation
setTimeout(() => {
explosion.remove();
}, 500);
}
function createFinalExplosion() {
const gameRect = gameBoard.getBoundingClientRect();
const x = gameRect.width / 2;
const y = gameRect.height / 2;
const explosion = document.createElement('div');
explosion.className = 'game-over-explosion';
explosion.style.left = `${x - 60}px`;
explosion.style.top = `${y - 60}px`;
gameBoard.appendChild(explosion);
// Remove explosion after animation
setTimeout(() => {
explosion.remove();
}, 1000);
}
function endGame() {
gameActive = false;
clearInterval(gameTimer);
// Clear all bombs
gameBoard.querySelectorAll('.bomb').forEach(bomb => {
clearTimeout(bomb.dataset.timer);
bomb.remove();
});
// Big final explosion
createFinalExplosion();
// Update high score if needed
if (score > highScore) {
highScore = score;
localStorage.setItem('highScore', highScore);
updateHighScoreDisplay();
}
// Update leaderboard
updateLeaderboard(score);
// Show game over screen after explosion
setTimeout(() => {
finalScoreDisplay.textContent = `SCORE: ${score}`;
gameOverScreen.style.display = 'flex';
document.body.classList.remove('danger');
}, 1000);
}
function restartGame() {
gameOverScreen.style.display = 'none';
gameBoard.innerHTML = '<div class="scanlines"></div>';
startGame();
}
function updateHighScoreDisplay() {
highScoreDisplay.textContent = `HIGH SCORE: ${highScore}`;
}
function updateLeaderboard(newScore) {
// Add new score to leaderboard
leaderboard.push(newScore);
// Sort in descending order and keep top 5
leaderboard.sort((a, b) => b - a);
leaderboard = leaderboard.slice(0, 5);
// Save to localStorage
localStorage.setItem('leaderboard', JSON.stringify(leaderboard));
updateLeaderboardDisplay();
}
function updateLeaderboardDisplay() {
leaderboardEntries.innerHTML = '';
leaderboard.forEach((score, index) => {
const entry = document.createElement('div');
entry.className = 'leaderboard-entry';
entry.innerHTML = `<span>${index + 1}.</span> <span>${score}</span>`;
leaderboardEntries.appendChild(entry);
});
}
</script>
</body>
</html>