Meta Description" name="description" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Fruit Catcher Mobile</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body, html {
width: 100%;
height: 100%;
overflow: hidden;
background-color: #e0f7fa;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
position: relative;
}
#gameCanvas {
display: block;
background: linear-gradient(to bottom, #87CEEB, #E0F6FF);
width: 100%;
height: 100%;
}
/* Mobile Touch Overlay Zones */
.touch-zone {
position: absolute;
bottom: 0;
width: 50%;
height: 80%; /* Higher touch zone for comfortable holding */
z-index: 10;
}
#leftZone { left: 0; }
#rightZone { right: 0; }
/* Game Over Screen */
#gameOverScreen {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
background: rgba(255, 255, 255, 0.95);
padding: 30px;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
z-index: 20;
width: 80%;
max-width: 300px;
}
h1 { color: #d32f2f; margin-bottom: 10px; font-size: 28px; }
p { color: #333; margin-bottom: 20px; font-size: 18px; }
button {
background-color: #4CAF50;
color: white;
border: none;
padding: 12px 25px;
font-size: 18px;
border-radius: 25px;
cursor: pointer;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<!-- Touch controls for mobile -->
<div id="leftZone" class="touch-zone"></div>
<div id="rightZone" class="touch-zone"></div>
<!-- UI Overlay -->
<div id="gameOverScreen">
<h1>Game Over!</h1>
<p>Score: <span id="finalScore">0</span></p>
<button onclick="resetGame()">Play Again</button>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gameOverScreen = document.getElementById('gameOverScreen');
const finalScoreText = document.getElementById('finalScore');
// Dynamically resize canvas to fit mobile screen
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// Game Variables
let score = 0;
let lives = 3;
let gameOver = false;
// Basket Object
const basket = {
width: 80,
height: 30,
x: canvas.width / 2 - 40,
y: canvas.height - 80,
speed: 7,
dx: 0
};
// Falling Items Array
let items = [];
let itemSpeed = 4;
let spawnRate = 0.02; // Probability per frame
// Mobile Touch Handling
const leftZone = document.getElementById('leftZone');
const rightZone = document.getElementById('rightZone');
leftZone.addEventListener('touchstart', (e) => { e.preventDefault(); basket.dx = -basket.speed; });
leftZone.addEventListener('touchend', (e) => { e.preventDefault(); if(basket.dx < 0) basket.dx = 0; });
rightZone.addEventListener('touchstart', (e) => { e.preventDefault(); basket.dx = basket.speed; });
rightZone.addEventListener('touchend', (e) => { e.preventDefault(); if(basket.dx > 0) basket.dx = 0; });
// Keyboard Fallback for testing on Desktop
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft' || e.key === 'a') basket.dx = -basket.speed;
if (e.key === 'ArrowRight' || e.key === 'd') basket.dx = basket.speed;
});
document.addEventListener('keyup', (e) => {
if ((e.key === 'ArrowLeft' || e.key === 'a') && basket.dx < 0) basket.dx = 0;
if ((e.key === 'ArrowRight' || e.key === 'd') && basket.dx > 0) basket.dx = 0;
});
function spawnItem() {
if (Math.random() < spawnRate) {
const radius = 15;
const x = Math.random() * (canvas.width - radius * 2) + radius;
items.push({ x: x, y: -radius, radius: radius, color: '#e53935' });
}
}
function update() {
if (gameOver) return;
// Move Basket & Keep in bounds
basket.x += basket.dx;
if (basket.x < 0) basket.x = 0;
if (basket.x + basket.width > canvas.width) basket.x = canvas.width - basket.width;
// Spawn & Update items
spawnItem();
for (let i = items.length - 1; i >= 0; i--) {
let item = items[i];
item.y += itemSpeed;
// Collision detection with basket
if (item.y + item.radius >= basket.y &&
item.y - item.radius <= basket.y + basket.height &&
item.x >= basket.x &&
item.x <= basket.x + basket.width) {
items.splice(i, 1);
score++;
// Gradually increase difficulty
if (score % 5 === 0) {
itemSpeed += 0.5;
spawnRate += 0.005;
}
continue;
}
// Missed item
if (item.y - item.radius > canvas.height) {
items.splice(i, 1);
lives--;
if (lives <= 0) {
endGame();
}
}
}
}
function draw() {
// Clear Canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw Basket (Simple vector styling)
ctx.fillStyle = '#8D6E63';
ctx.beginPath();
ctx.roundRect(basket.x, basket.y, basket.width, basket.height, 10);
ctx.fill();
// Draw Rim of Basket
ctx.fillStyle = '#5D4037';
ctx.fillRect(basket.x, basket.y, basket.width, 5);
// Draw Apples
items.forEach(item => {
ctx.fillStyle = item.color;
ctx.beginPath();
ctx.arc(item.x, item.y, item.radius, 0, Math.PI * 2);
ctx.fill();
// Little leaf
ctx.fillStyle = '#4CAF50';
ctx.fillRect(item.x - 2, item.y - item.radius - 2, 4, 4);
});
// Draw HUD (Heads Up Display)
ctx.fillStyle = '#333';
ctx.font = 'bold 20px sans-serif';
ctx.textAlign = 'left';
ctx.fillText('Score: ' + score, 20, 40);
ctx.textAlign = 'right';
ctx.fillText('❤️ '.repeat(lives), canvas.width - 20, 40);
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
function endGame() {
gameOver = true;
finalScoreText.innerText = score;
gameOverScreen.style.display = 'block';
}
function resetGame() {
score = 0;
lives = 3;
itemSpeed = 4;
spawnRate = 0.02;
items = [];
basket.x = canvas.width / 2 - 40;
basket.dx = 0;
gameOver = false;
gameOverScreen.style.display = 'none';
}
// Start the game
gameLoop();
</script>
</body>
</html>
1
1
9KB
9KB
486.0ms
580.0ms
489.0ms