snakegame / index.html
durgaamma2005's picture
Add 3 files
46f18e3 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Customizable Snake Game</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
#gameCanvas {
border: 2px solid #4a5568;
background-color: #f7fafc;
}
.toggle-btn {
transition: all 0.3s ease;
}
.toggle-btn.active {
background-color: #4299e1;
color: white;
}
.modal {
display: none;
position: fixed;
z-index: 10;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #f8fafc;
margin: 15% auto;
padding: 20px;
border-radius: 8px;
max-width: 400px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body class="bg-gray-100 min-h-screen flex flex-col items-center justify-center p-4">
<div class="text-center mb-6">
<h1 class="text-4xl font-bold text-gray-800 mb-2">Custom Snake Game</h1>
<p class="text-gray-600">Control the snake with arrow keys or WASD</p>
</div>
<div class="flex flex-col md:flex-row gap-8 items-center justify-center">
<div class="flex flex-col items-center">
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div class="mt-4 flex gap-4">
<button id="startBtn" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition">
Start Game
</button>
<button id="pauseBtn" class="px-4 py-2 bg-yellow-500 text-white rounded hover:bg-yellow-600 transition hidden">
Pause
</button>
<button id="restartBtn" class="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 transition">
Restart
</button>
</div>
</div>
<div class="bg-white p-6 rounded-lg shadow-lg w-full max-w-md">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Game Settings</h2>
<div class="mb-6">
<label class="block text-gray-700 mb-2">Game Speed</label>
<input type="range" id="speedSlider" min="5" max="25" value="10" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
<div class="flex justify-between text-sm text-gray-600 mt-1">
<span>Slow</span>
<span>Fast</span>
</div>
</div>
<div class="mb-6">
<label class="block text-gray-700 mb-2">Boundary Settings</label>
<p class="text-sm text-gray-500 mb-3">Select which boundaries will end the game:</p>
<div class="grid grid-cols-2 gap-2">
<button id="topBoundary" class="toggle-btn px-3 py-2 border rounded">Top</button>
<button id="rightBoundary" class="toggle-btn px-3 py-2 border rounded">Right</button>
<button id="bottomBoundary" class="toggle-btn px-3 py-2 border rounded active">Bottom</button>
<button id="leftBoundary" class="toggle-btn px-3 py-2 border rounded active">Left</button>
</div>
</div>
<div class="mb-4">
<label class="block text-gray-700 mb-2">Game Stats</label>
<div class="bg-gray-100 p-3 rounded">
<div class="flex justify-between">
<span class="font-medium">Score:</span>
<span id="scoreDisplay">0</span>
</div>
<div class="flex justify-between">
<span class="font-medium">High Score:</span>
<span id="highScoreDisplay">0</span>
</div>
</div>
</div>
<button id="howToPlayBtn" class="text-blue-500 hover:text-blue-700 text-sm underline">
How to Play
</button>
</div>
</div>
<!-- How to Play Modal -->
<div id="howToPlayModal" class="modal">
<div class="modal-content">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">How to Play</h3>
<button id="closeModal" class="text-gray-500 hover:text-gray-700">&times;</button>
</div>
<div class="space-y-3 text-gray-700">
<p><strong>Controls:</strong> Use arrow keys (↑, ↓, ←, →) or WASD keys to move the snake.</p>
<p><strong>Objective:</strong> Eat the food (red square) to grow longer and increase your score.</p>
<p><strong>Game Over:</strong> The game ends if you hit the selected boundaries or yourself.</p>
<p><strong>Customization:</strong> Adjust game speed and select which boundaries will end the game.</p>
</div>
<div class="mt-6 flex justify-center">
<button id="closeModalBtn" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition">
Got it!
</button>
</div>
</div>
</div>
<script>
// Game variables
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const boxSize = 20;
let snake = [];
let food = {};
let direction = 'right';
let nextDirection = 'right';
let gameSpeed = 150; // Initial slow speed (higher number = slower)
let gameInterval;
let score = 0;
let highScore = localStorage.getItem('snakeHighScore') || 0;
let gameRunning = false;
let gamePaused = false;
// Boundary settings
let boundaries = {
top: false,
right: false,
bottom: true,
left: true
};
// Initialize game
function initGame() {
snake = [
{x: 9 * boxSize, y: 10 * boxSize},
{x: 8 * boxSize, y: 10 * boxSize},
{x: 7 * boxSize, y: 10 * boxSize}
];
direction = 'right';
nextDirection = 'right';
score = 0;
updateScore();
generateFood();
}
// Draw game elements
function draw() {
// Clear canvas
ctx.fillStyle = '#f7fafc';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw snake
snake.forEach((segment, index) => {
if (index === 0) {
// Draw head with different color
ctx.fillStyle = '#2c5282';
} else {
ctx.fillStyle = '#4299e1';
}
ctx.fillRect(segment.x, segment.y, boxSize, boxSize);
ctx.strokeStyle = '#ebf8ff';
ctx.strokeRect(segment.x, segment.y, boxSize, boxSize);
});
// Draw food
ctx.fillStyle = '#e53e3e';
ctx.fillRect(food.x, food.y, boxSize, boxSize);
// Draw grid (optional)
if (window.innerWidth > 768) { // Only show grid on larger screens
ctx.strokeStyle = '#e2e8f0';
ctx.lineWidth = 0.5;
for (let i = 0; i < canvas.width; i += boxSize) {
ctx.beginPath();
ctx.moveTo(i, 0);
ctx.lineTo(i, canvas.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, i);
ctx.lineTo(canvas.width, i);
ctx.stroke();
}
}
}
// Game logic
function gameLoop() {
if (gamePaused) return;
// Update direction
direction = nextDirection;
// Calculate new head position
const head = {x: snake[0].x, y: snake[0].y};
switch (direction) {
case 'up':
head.y -= boxSize;
break;
case 'down':
head.y += boxSize;
break;
case 'left':
head.x -= boxSize;
break;
case 'right':
head.x += boxSize;
break;
}
// Check for collisions
if (checkCollision(head)) {
gameOver();
return;
}
// Add new head
snake.unshift(head);
// Check if snake ate food
if (head.x === food.x && head.y === food.y) {
score += 10;
updateScore();
generateFood();
} else {
// Remove tail if no food eaten
snake.pop();
}
// Redraw everything
draw();
}
// Check for collisions
function checkCollision(head) {
// Check wall collisions based on boundary settings
if (boundaries.top && head.y < 0) return true;
if (boundaries.right && head.x >= canvas.width) return true;
if (boundaries.bottom && head.y >= canvas.height) return true;
if (boundaries.left && head.x < 0) return true;
// Check self collision
for (let i = 0; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
return true;
}
}
return false;
}
// Generate food at random position
function generateFood() {
const maxX = Math.floor(canvas.width / boxSize);
const maxY = Math.floor(canvas.height / boxSize);
let foodX, foodY;
let validPosition = false;
while (!validPosition) {
foodX = Math.floor(Math.random() * maxX) * boxSize;
foodY = Math.floor(Math.random() * maxY) * boxSize;
validPosition = true;
// Check if food is on snake
for (let i = 0; i < snake.length; i++) {
if (snake[i].x === foodX && snake[i].y === foodY) {
validPosition = false;
break;
}
}
}
food = {x: foodX, y: foodY};
}
// Game over
function gameOver() {
clearInterval(gameInterval);
gameRunning = false;
document.getElementById('startBtn').classList.remove('hidden');
document.getElementById('pauseBtn').classList.add('hidden');
// Update high score if needed
if (score > highScore) {
highScore = score;
localStorage.setItem('snakeHighScore', highScore);
updateScore();
}
// Show game over message
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ffffff';
ctx.font = '30px Arial';
ctx.textAlign = 'center';
ctx.fillText('Game Over!', canvas.width / 2, canvas.height / 2 - 30);
ctx.font = '20px Arial';
ctx.fillText(`Score: ${score}`, canvas.width / 2, canvas.height / 2 + 10);
ctx.fillText(`High Score: ${highScore}`, canvas.width / 2, canvas.height / 2 + 40);
ctx.font = '16px Arial';
ctx.fillText('Press Restart to play again', canvas.width / 2, canvas.height / 2 + 80);
}
// Update score display
function updateScore() {
document.getElementById('scoreDisplay').textContent = score;
document.getElementById('highScoreDisplay').textContent = highScore;
}
// Start game
function startGame() {
if (gameRunning) return;
initGame();
gameRunning = true;
gamePaused = false;
clearInterval(gameInterval);
gameInterval = setInterval(gameLoop, gameSpeed);
document.getElementById('startBtn').classList.add('hidden');
document.getElementById('pauseBtn').classList.remove('hidden');
draw();
}
// Pause game
function pauseGame() {
if (!gameRunning) return;
gamePaused = !gamePaused;
if (gamePaused) {
document.getElementById('pauseBtn').textContent = 'Resume';
// Draw pause message
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ffffff';
ctx.font = '30px Arial';
ctx.textAlign = 'center';
ctx.fillText('Game Paused', canvas.width / 2, canvas.height / 2);
} else {
document.getElementById('pauseBtn').textContent = 'Pause';
}
}
// Restart game
function restartGame() {
clearInterval(gameInterval);
gameRunning = false;
gamePaused = false;
document.getElementById('startBtn').classList.remove('hidden');
document.getElementById('pauseBtn').classList.add('hidden');
document.getElementById('pauseBtn').textContent = 'Pause';
initGame();
draw();
}
// Event listeners
document.addEventListener('keydown', function(e) {
// Prevent default for arrow keys to avoid page scrolling
if ([37, 38, 39, 40].indexOf(e.keyCode) > -1) {
e.preventDefault();
}
// Change direction based on key press
switch(e.keyCode) {
case 37: // left arrow
case 65: // A
if (direction !== 'right') nextDirection = 'left';
break;
case 38: // up arrow
case 87: // W
if (direction !== 'down') nextDirection = 'up';
break;
case 39: // right arrow
case 68: // D
if (direction !== 'left') nextDirection = 'right';
break;
case 40: // down arrow
case 83: // S
if (direction !== 'up') nextDirection = 'down';
break;
case 32: // space
if (gameRunning) pauseGame();
break;
}
});
// UI event listeners
document.getElementById('startBtn').addEventListener('click', startGame);
document.getElementById('pauseBtn').addEventListener('click', pauseGame);
document.getElementById('restartBtn').addEventListener('click', restartGame);
// Speed control
document.getElementById('speedSlider').addEventListener('input', function() {
// Map slider value (5-25) to game speed (300-50ms)
gameSpeed = 300 - (this.value * 10);
if (gameRunning) {
clearInterval(gameInterval);
gameInterval = setInterval(gameLoop, gameSpeed);
}
});
// Boundary toggles
const boundaryButtons = ['top', 'right', 'bottom', 'left'];
boundaryButtons.forEach(boundary => {
document.getElementById(`${boundary}Boundary`).addEventListener('click', function() {
boundaries[boundary] = !boundaries[boundary];
this.classList.toggle('active');
this.classList.toggle('bg-blue-500');
this.classList.toggle('text-white');
});
});
// How to Play modal
const modal = document.getElementById('howToPlayModal');
document.getElementById('howToPlayBtn').addEventListener('click', function() {
modal.style.display = 'block';
});
document.getElementById('closeModal').addEventListener('click', function() {
modal.style.display = 'none';
});
document.getElementById('closeModalBtn').addEventListener('click', function() {
modal.style.display = 'none';
});
window.addEventListener('click', function(event) {
if (event.target === modal) {
modal.style.display = 'none';
}
});
// Initialize game display
initGame();
draw();
</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=durgaamma2005/snakegame" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>