DinoGame / index.html
cfalk43's picture
Upload folder using huggingface_hub
66e0807 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dino Runner Game</title>
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
font-family: 'Press Start 2P', cursive;
overflow: hidden;
}
header {
width: 100%;
padding: 1rem;
text-align: center;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-bottom: 2px solid rgba(255, 255, 255, 0.2);
}
header a {
color: #00d4ff;
text-decoration: none;
font-size: 0.7rem;
transition: all 0.3s ease;
}
header a:hover {
color: #fff;
text-shadow: 0 0 10px #00d4ff;
}
.game-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
padding: 2rem;
width: 100%;
max-width: 900px;
}
h1 {
color: #fff;
font-size: clamp(1rem, 4vw, 2rem);
margin-bottom: 1rem;
text-shadow: 0 0 20px rgba(0, 212, 255, 0.5);
text-align: center;
}
.score-board {
display: flex;
gap: 2rem;
margin-bottom: 1rem;
flex-wrap: wrap;
justify-content: center;
}
.score-item {
color: #fff;
font-size: clamp(0.6rem, 2vw, 0.9rem);
padding: 0.5rem 1rem;
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.score-item span {
color: #00d4ff;
}
#gameCanvas {
border: 4px solid #00d4ff;
border-radius: 15px;
box-shadow: 0 0 30px rgba(0, 212, 255, 0.3),
inset 0 0 50px rgba(0, 0, 0, 0.5);
background: linear-gradient(180deg, #87CEEB 0%, #E0F6FF 60%, #90EE90 60%, #228B22 100%);
max-width: 100%;
cursor: pointer;
}
.instructions {
color: rgba(255, 255, 255, 0.7);
font-size: clamp(0.5rem, 1.5vw, 0.7rem);
margin-top: 1rem;
text-align: center;
line-height: 2;
}
.instructions kbd {
background: rgba(255, 255, 255, 0.2);
padding: 0.3rem 0.6rem;
border-radius: 5px;
border: 1px solid rgba(255, 255, 255, 0.3);
}
.game-over-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: none;
justify-content: center;
align-items: center;
z-index: 100;
}
.game-over-content {
text-align: center;
color: #fff;
padding: 2rem;
background: linear-gradient(135deg, #1a1a2e, #16213e);
border-radius: 20px;
border: 3px solid #00d4ff;
box-shadow: 0 0 50px rgba(0, 212, 255, 0.5);
}
.game-over-content h2 {
font-size: clamp(1.5rem, 5vw, 2.5rem);
margin-bottom: 1rem;
color: #ff4757;
}
.game-over-content p {
font-size: clamp(0.7rem, 2vw, 1rem);
margin-bottom: 1.5rem;
}
.restart-btn {
font-family: 'Press Start 2P', cursive;
font-size: clamp(0.6rem, 2vw, 0.9rem);
padding: 1rem 2rem;
background: linear-gradient(135deg, #00d4ff, #0099cc);
color: #fff;
border: none;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
}
.restart-btn:hover {
transform: scale(1.05);
box-shadow: 0 0 20px rgba(0, 212, 255, 0.5);
}
.start-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
}
.start-content {
text-align: center;
color: #fff;
padding: 2rem;
}
.start-content h2 {
font-size: clamp(1.5rem, 5vw, 3rem);
margin-bottom: 2rem;
color: #00d4ff;
text-shadow: 0 0 30px rgba(0, 212, 255, 0.7);
}
.dino-art {
font-size: clamp(3rem, 10vw, 6rem);
margin-bottom: 2rem;
animation: bounce 1s infinite;
}
@keyframes bounce {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-20px);
}
}
.start-btn {
font-family: 'Press Start 2P', cursive;
font-size: clamp(0.8rem, 2.5vw, 1.2rem);
padding: 1.5rem 3rem;
background: linear-gradient(135deg, #00d4ff, #0099cc);
color: #fff;
border: none;
border-radius: 15px;
cursor: pointer;
transition: all 0.3s ease;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%,
100% {
box-shadow: 0 0 20px rgba(0, 212, 255, 0.5);
}
50% {
box-shadow: 0 0 40px rgba(0, 212, 255, 0.8);
}
}
.start-btn:hover {
transform: scale(1.1);
}
@media (max-width: 600px) {
.game-container {
padding: 1rem;
}
.score-board {
gap: 1rem;
}
}
</style>
</head>
<body>
<header>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">Built with anycoder</a>
</header>
<div class="start-screen" id="startScreen">
<div class="start-content">
<h2>🦖 DINO RUNNER 🦖</h2>
<div class="dino-art">🦕</div>
<button class="start-btn" id="startBtn">START GAME</button>
</div>
</div>
<div class="game-container">
<h1>🦖 DINO RUNNER 🦖</h1>
<div class="score-board">
<div class="score-item">SCORE: <span id="score">0</span></div>
<div class="score-item">HIGH SCORE: <span id="highScore">0</span></div>
</div>
<canvas id="gameCanvas" width="800" height="300"></canvas>
<div class="instructions">
Press <kbd>SPACE</kbd> or <kbd></kbd> to jump | <kbd></kbd> to duck | <kbd>TAP</kbd> on mobile
</div>
</div>
<div class="game-over-overlay" id="gameOverOverlay">
<div class="game-over-content">
<h2>GAME OVER!</h2>
<p>Your Score: <span id="finalScore">0</span></p>
<button class="restart-btn" id="restartBtn">PLAY AGAIN</button>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const highScoreElement = document.getElementById('highScore');
const finalScoreElement = document.getElementById('finalScore');
const gameOverOverlay = document.getElementById('gameOverOverlay');
const startScreen = document.getElementById('startScreen');
const startBtn = document.getElementById('startBtn');
const restartBtn = document.getElementById('restartBtn');
// Responsive canvas
function resizeCanvas() {
const maxWidth = Math.min(800, window.innerWidth - 40);
const ratio = 300 / 800;
canvas.style.width = maxWidth + 'px';
canvas.style.height = (maxWidth * ratio) + 'px';
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// Game variables
let gameRunning = false;
let gameSpeed = 6;
let score = 0;
let highScore = localStorage.getItem('dinoHighScore') || 0;
highScoreElement.textContent = highScore;
// Dino
const dino = {
x: 50,
y: 220,
width: 50,
height: 60,
velocityY: 0,
jumping: false,
ducking: false,
duckHeight: 35,
normalHeight: 60,
groundY: 220,
frame: 0,
frameCount: 0
};
// Obstacles
let obstacles = [];
let obstacleTimer = 0;
const obstacleInterval = 100;
// Clouds
let clouds = [];
// Ground
let groundX = 0;
// Physics
const gravity = 0.8;
const jumpForce = -15;
// Initialize clouds
function initClouds() {
clouds = [];
for (let i = 0; i < 5; i++) {
clouds.push({
x: Math.random() * canvas.width,
y: 30 + Math.random() * 60,
width: 60 + Math.random() * 40,
speed: 1 + Math.random()
});
}
}
// Draw cloud
function drawCloud(cloud) {
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.beginPath();
ctx.arc(cloud.x, cloud.y, 20, 0, Math.PI * 2);
ctx.arc(cloud.x + 25, cloud.y - 10, 25, 0, Math.PI * 2);
ctx.arc(cloud.x + 50, cloud.y, 20, 0, Math.PI * 2);
ctx.arc(cloud.x + 25, cloud.y + 5, 22, 0, Math.PI * 2);
ctx.fill();
}
// Draw dino
function drawDino() {
const height = dino.ducking ? dino.duckHeight : dino.normalHeight;
const y = dino.ducking ? dino.groundY + (dino.normalHeight - dino.duckHeight) : dino.y;
// Body
ctx.fillStyle = '#2d5016';
ctx.beginPath();
ctx.roundRect(dino.x, y, dino.width - 10, height, 10);
ctx.fill();
// Head
ctx.fillStyle = '#3d6b1e';
if (!dino.ducking) {
ctx.beginPath();
ctx.roundRect(dino.x + 15, y - 25, 35, 30, 8);
ctx.fill();
// Eye
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(dino.x + 40, y - 12, 6, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(dino.x + 42, y - 12, 3, 0, Math.PI * 2);
ctx.fill();
// Mouth
ctx.strokeStyle = '#1a3d0c';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(dino.x + 45, y - 5);
ctx.lineTo(dino.x + 50, y - 5);
ctx.stroke();
} else {
// Ducking head
ctx.beginPath();
ctx.roundRect(dino.x + 30, y - 5, 30, 20, 5);
ctx.fill();
// Eye when ducking
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(dino.x + 50, y + 5, 4, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(dino.x + 51, y + 5, 2, 0, Math.PI * 2);
ctx.fill();
}
// Legs animation
ctx.fillStyle = '#2d5016';
dino.frameCount++;
if (dino.frameCount > 5) {
dino.frame = (dino.frame + 1) % 2;
dino.frameCount = 0;
}
if (!dino.jumping) {
const legOffset = dino.frame === 0 ? 5 : -5;
ctx.fillRect(dino.x + 8, y + height - 5, 8, 15 + legOffset);
ctx.fillRect(dino.x + 25, y + height - 5, 8, 15 - legOffset);
} else {
ctx.fillRect(dino.x + 8, y + height - 5, 8, 12);
ctx.fillRect(dino.x + 25, y + height - 5, 8, 12);
}
// Tail
ctx.fillStyle = '#3d6b1e';
ctx.beginPath();
ctx.moveTo(dino.x, y + 20);
ctx.lineTo(dino.x - 20, y + 15);
ctx.lineTo(dino.x, y + 35);
ctx.fill();
}
// Draw cactus obstacle
function drawCactus(obstacle) {
ctx.fillStyle = '#228B22';
// Main stem
ctx.beginPath();
ctx.roundRect(obstacle.x + 10, obstacle.y, 20, obstacle.height, 5);
ctx.fill();
// Left arm
ctx.beginPath();
ctx.roundRect(obstacle.x, obstacle.y + 15, 12, 25, 4);
ctx.fill();
ctx.beginPath();
ctx.roundRect(obstacle.x, obstacle.y + 10, 8, 15, 3);
ctx.fill();
// Right arm
ctx.beginPath();
ctx.roundRect(obstacle.x + 28, obstacle.y + 25, 12, 20, 4);
ctx.fill();
ctx.beginPath();
ctx.roundRect(obstacle.x + 32, obstacle.y + 20, 8, 12, 3);
ctx.fill();
// Spikes
ctx.fillStyle = '#1a6b1a';
for (let i = 0; i < 5; i++) {
ctx.beginPath();
ctx.arc(obstacle.x + 20, obstacle.y + i * 12, 2, 0, Math.PI * 2);
ctx.fill();
}
}
// Draw bird obstacle
function drawBird(obstacle) {
ctx.fillStyle = '#8B4513';
// Body
ctx.beginPath();
ctx.ellipse(obstacle.x + 20, obstacle.y + 15, 20, 12, 0, 0, Math.PI * 2);
ctx.fill();
// Head
ctx.beginPath();
ctx.arc(obstacle.x + 40, obstacle.y + 10, 10, 0, Math.PI * 2);
ctx.fill();
// Beak
ctx.fillStyle = '#FFA500';
ctx.beginPath();
ctx.moveTo(obstacle.x + 50, obstacle.y + 10);
ctx.lineTo(obstacle.x + 60, obstacle.y + 12);
ctx.lineTo(obstacle.x + 50, obstacle.y + 14);
ctx.fill();
// Eye
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(obstacle.x + 43, obstacle.y + 8, 4, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(obstacle.x + 44, obstacle.y + 8, 2, 0, Math.PI * 2);
ctx.fill();
// Wings animation
ctx.fillStyle = '#6B3E26';
const wingY = Math.sin(Date.now() / 100) * 10;
ctx.beginPath();
ctx.moveTo(obstacle.x + 10, obstacle.y + 15);
ctx.lineTo(obstacle.x - 10, obstacle.y + wingY);
ctx.lineTo(obstacle.x + 20, obstacle.y + 15);
ctx.fill();
}
// Draw ground
function drawGround() {
ctx.fillStyle = '#8B4513';
ctx.fillRect(0, 280, canvas.width, 20);
ctx.fillStyle = '#654321';
groundX -= gameSpeed;
if (groundX <= -20) groundX = 0;
for (let i = groundX; i < canvas.width; i += 20) {
ctx.fillRect(i, 282, 15, 3);
ctx.fillRect(i + 7, 288, 10, 2);
}
// Grass
ctx.fillStyle = '#228B22';
ctx.fillRect(0, 275, canvas.width, 5);
}
// Spawn obstacle
function spawnObstacle() {
const type = Math.random() > 0.7 ? 'bird' : 'cactus';
const obstacle = {
x: canvas.width,
type: type,
width: type === 'cactus' ? 40 : 60,
height: type === 'cactus' ? 50 + Math.random() * 20 : 30
};
if (type === 'cactus') {
obstacle.y = 280 - obstacle.height;
} else {
obstacle.y = Math.random() > 0.5 ? 180 : 230;
}
obstacles.push(obstacle);
}
// Check collision
function checkCollision() {
const dinoHeight = dino.ducking ? dino.duckHeight : dino.normalHeight;
const dinoY = dino.ducking ? dino.groundY + (dino.normalHeight - dino.duckHeight) : dino.y;
for (let obstacle of obstacles) {
if (dino.x + dino.width - 15 > obstacle.x &&
dino.x + 10 < obstacle.x + obstacle.width &&
dinoY + dinoHeight > obstacle.y &&
dinoY < obstacle.y + obstacle.height) {
return true;
}
}
return false;
}
// Game over
function gameOver() {
gameRunning = false;
finalScoreElement.textContent = score;
if (score > highScore) {
highScore = score;
localStorage.setItem('dinoHighScore', highScore);
highScoreElement.textContent = highScore;
}
gameOverOverlay.style.display = 'flex';
}
// Reset game
function resetGame() {
score = 0;
gameSpeed = 6;
obstacles = [];
obstacleTimer = 0;
dino.y = dino.groundY;
dino.velocityY = 0;
dino.jumping = false;
dino.ducking = false;
initClouds();
gameOverOverlay.style.display = 'none';
gameRunning = true;
gameLoop();
}
// Update game
function update() {
// Dino physics
if (dino.jumping) {
dino.velocityY += gravity;
dino.y += dino.velocityY;
if (dino.y >= dino.groundY) {
dino.y = dino.groundY;
dino.jumping = false;
dino.velocityY = 0;
}
}
// Update obstacles
obstacleTimer++;
if (obstacleTimer >= obstacleInterval - Math.min(score / 10, 50)) {
spawnObstacle();
obstacleTimer = 0;
}
for (let i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].x -= gameSpeed;
if (obstacles[i].x + obstacles[i].width < 0) {
obstacles.splice(i, 1);
score++;
scoreElement.textContent = score;
}
}
// Update clouds
for (let cloud of clouds) {
cloud.x -= cloud.speed;
if (cloud.x + cloud.width < 0) {
cloud.x = canvas.width + 50;
cloud.y = 30 + Math.random() * 60;
}
}
// Increase speed
if (score > 0 && score % 10 === 0) {
gameSpeed = 6 + Math.floor(score / 10) * 0.5;
}
// Check collision
if (checkCollision()) {
gameOver();
}
}
// Draw game
function draw() {
// Sky gradient
const gradient = ctx.createLinearGradient(0, 0, 0, 280);
gradient.addColorStop(0, '#87CEEB');
gradient.addColorStop(0.6, '#E0F6FF');
gradient.addColorStop(0.6, '#90EE90');
gradient.addColorStop(1, '#228B22');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Sun
ctx.fillStyle = '#FFD700';
ctx.beginPath();
ctx.arc(700, 50, 30, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = 'rgba(255, 215, 0, 0.3)';
ctx.beginPath();
ctx.arc(700, 50, 45, 0, Math.PI * 2);
ctx.fill();
// Clouds
for (let cloud of clouds) {
drawCloud(cloud);
}
// Ground
drawGround();
// Obstacles
for (let obstacle of obstacles) {
if (obstacle.type === 'cactus') {
drawCactus(obstacle);
} else {
drawBird(obstacle);
}
}
// Dino
drawDino();
}
// Game loop
function gameLoop() {
if (!gameRunning) return;
update();
draw();
requestAnimationFrame(gameLoop);
}
// Controls
function jump() {
if (!dino.jumping && !dino.ducking) {
dino.jumping = true;
dino.velocityY = jumpForce;
}
}
function duck(isDucking) {
if (!dino.jumping) {
dino.ducking = isDucking;
}
}
// Event listeners
document.addEventListener('keydown', (e) => {
if (!gameRunning) return;
if (e.code === 'Space' || e.code === 'ArrowUp') {
e.preventDefault();
jump();
}
if (e.code === 'ArrowDown') {
e.preventDefault();
duck(true);
}
});
document.addEventListener('keyup', (e) => {
if (e.code === 'ArrowDown') {
duck(false);
}
});
// Touch controls
canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
if (gameRunning) {
const touch = e.touches[0];
const rect = canvas.getBoundingClientRect();
const y = touch.clientY - rect.top;
if (y > rect.height / 2) {
duck(true);
} else {
jump();
}
}
});
canvas.addEventListener('touchend', (e) => {
duck(false);
});
canvas.addEventListener('click', () => {
if (gameRunning) {
jump();
}
});
// Start and restart buttons
startBtn.addEventListener('click', () => {
startScreen.style.display = 'none';
resetGame();
});
restartBtn.addEventListener('click', resetGame);
// Initialize
initClouds();
draw();
</script>
</body>
</html>