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>Dungeon Collector</title>
<style>
body {
margin: 0;
background: #111;
color: white;
font-family: sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
}
#scoreBoard {
font-size: 24px;
margin-bottom: 10px;
font-weight: bold;
}
canvas {
background: #222;
border: 4px solid #444;
box-shadow: 0 0 20px rgba(0,0,0,0.8);
max-width: 100vw;
max-height: 70vh;
}
#msg {
margin-top: 15px;
font-size: 16px;
color: #aaa;
text-align: center;
}
</style>
</head>
<body>
<div id="scoreBoard">Coins: <span id="score">0</span></div>
<canvas id="gameCanvas" width="400" height="500"></canvas>
<div id="msg">Tap/Hold anywhere to move toward your touch!</div>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const scoreEl = document.getElementById("score");
let score = 0;
let gameOver = false;
// Player
const player = { x: 200, y: 400, radius: 15, speed: 4, color: "#00ffcc" };
// Target/Touch Position
let target = { x: player.x, y: player.y };
let isTouching = false;
// Coin
const coin = { x: 200, y: 150, radius: 10, color: "#ffd700" };
// Obstacles (Dungeon Guards)
const enemies = [
{ x: 50, y: 100, speedX: 3, radius: 12, color: "#ff4444" },
{ x: 350, y: 250, speedX: -4, radius: 12, color: "#ff4444" }
];
// Input Listeners for Mobile & Desktop
window.addEventListener("touchstart", (e) => { isTouching = true; updateTarget(e.touches[0]); });
window.addEventListener("touchmove", (e) => { updateTarget(e.touches[0]); });
window.addEventListener("touchend", () => { isTouching = false; });
window.addEventListener("mousedown", (e) => { isTouching = true; updateTarget(e); });
window.addEventListener("mousemove", (e) => { if(isTouching) updateTarget(e); });
window.addEventListener("mouseup", () => { isTouching = false; });
function updateTarget(e) {
const rect = canvas.getBoundingClientRect();
target.x = (e.clientX - rect.left) * (canvas.width / rect.width);
target.y = (e.clientY - rect.top) * (canvas.height / rect.height);
if (gameOver) resetGame();
}
function spawnCoin() {
coin.x = Math.random() * (canvas.width - 40) + 20;
coin.y = Math.random() * (canvas.height - 40) + 20;
}
function resetGame() {
score = 0;
scoreEl.innerText = score;
player.x = 200; player.y = 400;
target.x = player.x; target.y = player.y;
gameOver = false;
spawnCoin();
}
// Game Loop
function update() {
if (gameOver) {
ctx.fillStyle = "rgba(0,0,0,0.7)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#ff4444";
ctx.font = "30px sans-serif";
ctx.textAlign = "center";
ctx.fillText("GAME OVER", canvas.width/2, canvas.height/2);
ctx.fillStyle = "#fff";
ctx.font = "16px sans-serif";
ctx.fillText("Tap to Restart", canvas.width/2, canvas.height/2 + 40);
requestAnimationFrame(update);
return;
}
// Clear Canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Move Player smoothly towards target/touch position
if (isTouching) {
let dx = target.x - player.x;
let dy = target.y - player.y;
let dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 5) {
player.x += (dx / dist) * player.speed;
player.y += (dy / dist) * player.speed;
}
}
// Draw Player
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2);
ctx.fillStyle = player.color;
ctx.fill();
ctx.closePath();
// Draw Coin
ctx.beginPath();
ctx.arc(coin.x, coin.y, coin.radius, 0, Math.PI * 2);
ctx.fillStyle = coin.color;
ctx.fill();
ctx.closePath();
// Check Coin Collision
let distX = player.x - coin.x;
let distY = player.y - coin.y;
if (Math.sqrt(distX * distX + distY * distY) < player.radius + coin.radius) {
score++;
scoreEl.innerText = score;
spawnCoin();
}
// Update and Draw Enemies
enemies.forEach(enemy => {
enemy.x += enemy.speedX;
// Bounce off walls
if (enemy.x - enemy.radius < 0 || enemy.x + enemy.radius > canvas.width) {
enemy.speedX *= -1;
}
ctx.beginPath();
ctx.arc(enemy.x, enemy.y, enemy.radius, 0, Math.PI * 2);
ctx.fillStyle = enemy.color;
ctx.fill();
ctx.closePath();
// Check Enemy Collision
let eDistX = player.x - enemy.x;
let eDistY = player.y - enemy.y;
if (Math.sqrt(eDistX * eDistX + eDistY * eDistY) < player.radius + enemy.radius) {
gameOver = true;
}
});
requestAnimationFrame(update);
}
spawnCoin();
update();
</script>
</body>
</html>
1
1
6KB
6KB
100.0ms
124.0ms
101.0ms