|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Pake Mane Game</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<style> |
|
|
@keyframes fall { |
|
|
from { transform: translateY(-100px); } |
|
|
to { transform: translateY(calc(100vh - 100px)); } |
|
|
} |
|
|
|
|
|
.falling-item { |
|
|
animation: fall linear forwards; |
|
|
position: absolute; |
|
|
width: 50px; |
|
|
height: 50px; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
font-size: 24px; |
|
|
} |
|
|
|
|
|
#gameArea { |
|
|
position: relative; |
|
|
width: 100%; |
|
|
height: calc(100vh - 100px); |
|
|
overflow: hidden; |
|
|
background-color: #f0f9ff; |
|
|
} |
|
|
|
|
|
#basket { |
|
|
transition: left 0.1s ease-out; |
|
|
} |
|
|
|
|
|
.score-bounce { |
|
|
animation: scoreBounce 0.5s; |
|
|
} |
|
|
|
|
|
@keyframes scoreBounce { |
|
|
0%, 100% { transform: scale(1); } |
|
|
50% { transform: scale(1.5); } |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-blue-50 min-h-screen flex flex-col items-center"> |
|
|
<div class="container mx-auto px-4 py-8"> |
|
|
<h1 class="text-4xl font-bold text-center text-blue-600 mb-2">Pake Mane</h1> |
|
|
<p class="text-center text-blue-500 mb-6">Catch the falling items with your basket!</p> |
|
|
|
|
|
<div class="flex justify-between items-center mb-4"> |
|
|
<div class="text-xl font-semibold"> |
|
|
Score: <span id="score" class="text-blue-600">0</span> |
|
|
</div> |
|
|
<div class="text-xl font-semibold"> |
|
|
Time: <span id="time" class="text-blue-600">60</span>s |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div id="gameArea" class="border-2 border-blue-300 rounded-lg bg-gradient-to-b from-blue-100 to-blue-200"> |
|
|
<div id="basket" class="absolute bottom-0 w-24 h-16 bg-orange-500 rounded-t-lg flex items-center justify-center"> |
|
|
<div class="w-full h-2 bg-orange-700 rounded-full"></div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="mt-6 flex justify-center space-x-4"> |
|
|
<button id="startBtn" class="px-6 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition"> |
|
|
Start Game |
|
|
</button> |
|
|
<button id="resetBtn" class="px-6 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition"> |
|
|
Reset |
|
|
</button> |
|
|
</div> |
|
|
|
|
|
<div class="mt-8 bg-white p-4 rounded-lg shadow-md"> |
|
|
<h2 class="text-xl font-semibold text-blue-600 mb-2">How to Play</h2> |
|
|
<ul class="list-disc pl-5 space-y-1"> |
|
|
<li>Use mouse or touch to move the basket left and right</li> |
|
|
<li>Catch as many items as you can in 60 seconds</li> |
|
|
<li>Different items give different points</li> |
|
|
<li>Avoid the bombs that deduct points!</li> |
|
|
</ul> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
const gameArea = document.getElementById('gameArea'); |
|
|
const basket = document.getElementById('basket'); |
|
|
const scoreDisplay = document.getElementById('score'); |
|
|
const timeDisplay = document.getElementById('time'); |
|
|
const startBtn = document.getElementById('startBtn'); |
|
|
const resetBtn = document.getElementById('resetBtn'); |
|
|
|
|
|
let score = 0; |
|
|
let timeLeft = 60; |
|
|
let gameInterval; |
|
|
let timeInterval; |
|
|
let isGameRunning = false; |
|
|
let gameWidth = gameArea.offsetWidth; |
|
|
let basketWidth = basket.offsetWidth; |
|
|
|
|
|
|
|
|
const items = [ |
|
|
{ emoji: '🍎', points: 1, color: 'bg-red-400' }, |
|
|
{ emoji: '🍌', points: 2, color: 'bg-yellow-300' }, |
|
|
{ emoji: '🍇', points: 3, color: 'bg-purple-400' }, |
|
|
{ emoji: '🍒', points: 2, color: 'bg-red-500' }, |
|
|
{ emoji: '💣', points: -5, color: 'bg-gray-700' } |
|
|
]; |
|
|
|
|
|
|
|
|
gameArea.addEventListener('mousemove', moveBasket); |
|
|
gameArea.addEventListener('touchmove', (e) => { |
|
|
e.preventDefault(); |
|
|
const touch = e.touches[0]; |
|
|
moveBasket({ clientX: touch.clientX }); |
|
|
}); |
|
|
|
|
|
function moveBasket(e) { |
|
|
if (!isGameRunning) return; |
|
|
|
|
|
const gameRect = gameArea.getBoundingClientRect(); |
|
|
let newPosition = e.clientX - gameRect.left - basketWidth / 2; |
|
|
|
|
|
|
|
|
newPosition = Math.max(0, Math.min(newPosition, gameWidth - basketWidth)); |
|
|
|
|
|
basket.style.left = `${newPosition}px`; |
|
|
} |
|
|
|
|
|
function createFallingItem() { |
|
|
if (!isGameRunning) return; |
|
|
|
|
|
const item = items[Math.floor(Math.random() * items.length)]; |
|
|
const itemElement = document.createElement('div'); |
|
|
itemElement.className = `falling-item ${item.color} rounded-full shadow-md`; |
|
|
itemElement.textContent = item.emoji; |
|
|
|
|
|
const startPosition = Math.random() * (gameWidth - 50); |
|
|
itemElement.style.left = `${startPosition}px`; |
|
|
|
|
|
|
|
|
const duration = 3 + Math.random() * 4; |
|
|
itemElement.style.animationDuration = `${duration}s`; |
|
|
|
|
|
gameArea.appendChild(itemElement); |
|
|
|
|
|
|
|
|
const checkCollision = setInterval(() => { |
|
|
const itemRect = itemElement.getBoundingClientRect(); |
|
|
const basketRect = basket.getBoundingClientRect(); |
|
|
|
|
|
if ( |
|
|
itemRect.bottom >= basketRect.top && |
|
|
itemRect.right >= basketRect.left && |
|
|
itemRect.left <= basketRect.right |
|
|
) { |
|
|
|
|
|
clearInterval(checkCollision); |
|
|
updateScore(item.points); |
|
|
itemElement.remove(); |
|
|
|
|
|
|
|
|
const feedback = document.createElement('div'); |
|
|
feedback.className = 'absolute text-xl font-bold'; |
|
|
feedback.textContent = item.points > 0 ? `+${item.points}` : `${item.points}`; |
|
|
feedback.style.color = item.points > 0 ? 'green' : 'red'; |
|
|
feedback.style.left = `${itemRect.left}px`; |
|
|
feedback.style.top = `${itemRect.top}px`; |
|
|
gameArea.appendChild(feedback); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
feedback.style.transition = 'all 0.5s'; |
|
|
feedback.style.opacity = '0'; |
|
|
feedback.style.transform = 'translateY(-20px)'; |
|
|
setTimeout(() => feedback.remove(), 500); |
|
|
}, 100); |
|
|
} |
|
|
|
|
|
|
|
|
if (itemRect.top >= gameArea.offsetHeight) { |
|
|
clearInterval(checkCollision); |
|
|
itemElement.remove(); |
|
|
} |
|
|
}, 16); |
|
|
} |
|
|
|
|
|
function updateScore(points) { |
|
|
score += points; |
|
|
score = Math.max(0, score); |
|
|
scoreDisplay.textContent = score; |
|
|
scoreDisplay.classList.add('score-bounce'); |
|
|
setTimeout(() => scoreDisplay.classList.remove('score-bounce'), 500); |
|
|
} |
|
|
|
|
|
function updateTimer() { |
|
|
timeLeft--; |
|
|
timeDisplay.textContent = timeLeft; |
|
|
|
|
|
if (timeLeft <= 10) { |
|
|
timeDisplay.classList.add('text-red-500'); |
|
|
} |
|
|
|
|
|
if (timeLeft <= 0) { |
|
|
endGame(); |
|
|
} |
|
|
} |
|
|
|
|
|
function startGame() { |
|
|
if (isGameRunning) return; |
|
|
|
|
|
isGameRunning = true; |
|
|
score = 0; |
|
|
timeLeft = 60; |
|
|
scoreDisplay.textContent = score; |
|
|
timeDisplay.textContent = timeLeft; |
|
|
timeDisplay.classList.remove('text-red-500'); |
|
|
|
|
|
|
|
|
document.querySelectorAll('.falling-item').forEach(item => item.remove()); |
|
|
|
|
|
|
|
|
gameInterval = setInterval(createFallingItem, 800); |
|
|
timeInterval = setInterval(updateTimer, 1000); |
|
|
|
|
|
startBtn.disabled = true; |
|
|
startBtn.classList.add('opacity-50'); |
|
|
} |
|
|
|
|
|
function endGame() { |
|
|
isGameRunning = false; |
|
|
clearInterval(gameInterval); |
|
|
clearInterval(timeInterval); |
|
|
|
|
|
startBtn.disabled = false; |
|
|
startBtn.classList.remove('opacity-50'); |
|
|
|
|
|
|
|
|
const gameOver = document.createElement('div'); |
|
|
gameOver.className = 'absolute inset-0 flex items-center justify-center bg-black bg-opacity-70 text-white text-3xl font-bold'; |
|
|
gameOver.textContent = `Game Over! Score: ${score}`; |
|
|
gameArea.appendChild(gameOver); |
|
|
|
|
|
setTimeout(() => gameOver.remove(), 3000); |
|
|
} |
|
|
|
|
|
function resetGame() { |
|
|
endGame(); |
|
|
score = 0; |
|
|
timeLeft = 60; |
|
|
scoreDisplay.textContent = score; |
|
|
timeDisplay.textContent = timeLeft; |
|
|
timeDisplay.classList.remove('text-red-500'); |
|
|
document.querySelectorAll('.falling-item').forEach(item => item.remove()); |
|
|
} |
|
|
|
|
|
startBtn.addEventListener('click', startGame); |
|
|
resetBtn.addEventListener('click', resetGame); |
|
|
|
|
|
|
|
|
window.addEventListener('resize', () => { |
|
|
gameWidth = gameArea.offsetWidth; |
|
|
}); |
|
|
</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=dlma/subway" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |