Meta Description" name="description" />
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Monkey Survivor 3D-ish</title>
<style>
body { margin: 0; background: #1a3311; overflow: hidden; touch-action: none; font-family: 'Arial Black', sans-serif; }
#ui { position: absolute; top: 10px; left: 10px; color: #fff; z-index: 100; pointer-events: none; }
#health-bar { width: 200px; height: 20px; background: red; border: 2px solid white; margin-top: 5px; }
#health-inner { width: 100%; height: 100%; background: #00ff00; transition: 0.2s; }
#status { position: absolute; top: 50%; width: 100%; text-align: center; color: yellow; font-size: 30px; text-shadow: 3px 3px #000; z-index: 100; }
canvas { display: block; }
</style>
</head>
<body>
<div id="ui">
KILLS: <span id="score">0</span>
<div>HEALTH</div>
<div id="health-bar"><div id="health-inner"></div></div>
</div>
<div id="status">WAITING FOR PLANE...</div>
<canvas id="gameCanvas"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreText = document.getElementById('score');
const healthInner = document.getElementById('health-inner');
const statusText = document.getElementById('status');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let score = 0;
let health = 100;
let gameState = "plane";
let planeX = -300;
let player = { x: canvas.width/2, y: canvas.height - 100, radius: 25 };
let enemies = [];
let enemyBullets = [];
let flash = false;
let isGameOver = false;
function drawSoldier(x, y, color, hasGun, isEnemy = false, angle = 0) {
ctx.save();
ctx.translate(x, y);
// Body (Vest look)
ctx.fillStyle = color;
ctx.fillRect(-15, -15, 30, 30);
// Head
ctx.fillStyle = "#D2B48C";
ctx.beginPath(); ctx.arc(0, -20, 12, 0, Math.PI * 2); ctx.fill();
// Eyes (Real look)
ctx.fillStyle = "white";
ctx.beginPath(); ctx.arc(-5, -22, 3, 0, Math.PI * 2); ctx.arc(5, -22, 3, 0, Math.PI * 2); ctx.fill();
ctx.fillStyle = "black";
ctx.beginPath(); ctx.arc(-5, -22, 1.5, 0, Math.PI * 2); ctx.arc(5, -22, 1.5, 0, Math.PI * 2); ctx.fill();
// Real Gun
if (hasGun) {
ctx.fillStyle = "#333";
ctx.fillRect(10, -5, 35, 8); // Barrel
ctx.fillRect(12, 2, 6, 10); // Grip
if(flash && !isEnemy) {
ctx.fillStyle = "orange";
ctx.beginPath(); ctx.arc(50, -1, 10, 0, Math.PI*2); ctx.fill();
}
}
ctx.restore();
}
function spawnEnemy() {
return {
x: Math.random() * (canvas.width - 60) + 30,
y: Math.random() * (canvas.height / 2),
speedX: (Math.random() - 0.5) * 5,
shootTimer: Math.random() * 100
};
}
function animate() {
if(isGameOver) return;
ctx.fillStyle = "#2d5a27"; // Grass
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (gameState === "plane") {
ctx.fillStyle = "silver"; ctx.fillRect(planeX, 100, 250, 60);
planeX += 6;
if (planeX > canvas.width / 2) statusText.innerText = "TAP TO DROP!";
if (planeX > canvas.width + 300) { gameState = "parachute"; planeX = -300; }
}
if (gameState === "parachute") {
statusText.innerText = "LANDING...";
drawSoldier(player.x, player.y, "#1b4d3e", true);
player.y = canvas.height - 150;
setTimeout(() => {
gameState = "fight";
statusText.innerText = "";
for(let i=0; i<4; i++) enemies.push(spawnEnemy());
}, 1000);
}
if (gameState === "fight") {
drawSoldier(player.x, player.y, "#1b4d3e", true);
// Enemies Logic
enemies.forEach((en, eIdx) => {
drawSoldier(en.x, en.y, "#7a1a1a", true, true);
en.x += en.speedX;
if(en.x < 0 || en.x > canvas.width) en.speedX *= -1;
// Enemy Shooting
en.shootTimer++;
if(en.shootTimer > 80) {
enemyBullets.push({ x: en.x, y: en.y + 20 });
en.shootTimer = 0;
}
});
// Enemy Bullets Logic
enemyBullets.forEach((b, bIdx) => {
ctx.fillStyle = "yellow";
ctx.beginPath(); ctx.arc(b.x, b.y, 5, 0, Math.PI*2); ctx.fill();
b.y += 7; // Bullet speed
// Hit Player Detection
let d = Math.hypot(b.x - player.x, b.y - player.y);
if(d < 30) {
health -= 10;
healthInner.style.width = health + "%";
enemyBullets.splice(bIdx, 1);
if(health <= 0) {
isGameOver = true;
statusText.innerText = "ELIMINATED! GAME OVER";
statusText.style.color = "red";
}
}
if(b.y > canvas.height) enemyBullets.splice(bIdx, 1);
});
}
requestAnimationFrame(animate);
}
window.addEventListener('mousedown', (e) => {
if (gameState === "plane") { gameState = "parachute"; }
else if (gameState === "fight") {
flash = true; setTimeout(() => flash = false, 50);
enemies.forEach((en, index) => {
let dist = Math.hypot(e.clientX - en.x, e.clientY - en.y);
if (dist < 45) {
enemies.splice(index, 1);
score++; scoreText.innerText = score;
setTimeout(() => enemies.push(spawnEnemy()), 1500);
}
});
}
});
animate();
</script>
</body>
</html>
1
1
6KB
6KB
118.0ms
192.0ms
118.0ms