Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Neon Snake - Futuristic Snake Game</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap'); | |
| body { | |
| font-family: 'Orbitron', sans-serif; | |
| background-color: #0f0f1a; | |
| overflow: hidden; | |
| user-select: none; | |
| } | |
| .game-container { | |
| position: relative; | |
| box-shadow: 0 0 30px rgba(0, 255, 255, 0.3); | |
| border: 2px solid rgba(0, 255, 255, 0.5); | |
| } | |
| .grid-cell { | |
| border: 1px solid rgba(255, 255, 255, 0.05); | |
| } | |
| .snake-head { | |
| background: linear-gradient(135deg, #00ffaa, #00aaff); | |
| box-shadow: 0 0 15px rgba(0, 255, 255, 0.7); | |
| } | |
| .snake-body { | |
| background: linear-gradient(135deg, #00aaff, #00ffaa); | |
| box-shadow: 0 0 10px rgba(0, 255, 255, 0.5); | |
| } | |
| .food { | |
| background: linear-gradient(135deg, #ff00aa, #ff5500); | |
| box-shadow: 0 0 20px rgba(255, 0, 170, 0.7); | |
| animation: pulse 1.5s infinite alternate; | |
| } | |
| @keyframes pulse { | |
| 0% { transform: scale(1); } | |
| 100% { transform: scale(1.2); } | |
| } | |
| .glow-text { | |
| text-shadow: 0 0 10px rgba(0, 255, 255, 0.7); | |
| } | |
| .neon-btn { | |
| transition: all 0.3s; | |
| box-shadow: 0 0 15px rgba(0, 255, 255, 0.5); | |
| } | |
| .neon-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 0 25px rgba(0, 255, 255, 0.8); | |
| } | |
| .particle { | |
| position: absolute; | |
| background-color: rgba(0, 255, 255, 0.7); | |
| border-radius: 50%; | |
| pointer-events: none; | |
| } | |
| .game-overlay { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(15, 15, 26, 0.8); | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 10; | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen flex flex-col items-center justify-center p-4"> | |
| <div class="text-center mb-6"> | |
| <h1 class="text-5xl font-bold text-cyan-400 glow-text mb-2">NEON SNAKE</h1> | |
| <p class="text-purple-300 text-lg">A futuristic twist on the classic game</p> | |
| </div> | |
| <div class="relative"> | |
| <div id="game-board" class="game-container bg-gray-900 rounded-lg"></div> | |
| <div id="game-overlay" class="game-overlay rounded-lg hidden"> | |
| <h2 class="text-4xl font-bold text-red-500 glow-text mb-4">GAME OVER</h2> | |
| <p class="text-2xl text-cyan-300 mb-6">Score: <span id="final-score">0</span></p> | |
| <button id="restart-btn" class="neon-btn bg-cyan-600 hover:bg-cyan-500 text-white font-bold py-3 px-6 rounded-full text-lg flex items-center"> | |
| <i class="fas fa-redo mr-2"></i> Play Again | |
| </button> | |
| </div> | |
| </div> | |
| <div class="mt-8 flex flex-col md:flex-row items-center justify-center gap-8"> | |
| <div class="bg-gray-800 bg-opacity-50 p-4 rounded-lg border border-cyan-500 border-opacity-30"> | |
| <h3 class="text-xl text-cyan-300 font-bold mb-2">Controls</h3> | |
| <div class="grid grid-cols-3 gap-2 text-center"> | |
| <div></div> | |
| <button class="control-btn bg-gray-700 hover:bg-gray-600 text-cyan-300 p-2 rounded"> | |
| <i class="fas fa-arrow-up"></i> | |
| </button> | |
| <div></div> | |
| <button class="control-btn bg-gray-700 hover:bg-gray-600 text-cyan-300 p-2 rounded"> | |
| <i class="fas fa-arrow-left"></i> | |
| </button> | |
| <button class="control-btn bg-gray-700 hover:bg-gray-600 text-cyan-300 p-2 rounded"> | |
| <i class="fas fa-arrow-down"></i> | |
| </button> | |
| <button class="control-btn bg-gray-700 hover:bg-gray-600 text-cyan-300 p-2 rounded"> | |
| <i class="fas fa-arrow-right"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="bg-gray-800 bg-opacity-50 p-4 rounded-lg border border-cyan-500 border-opacity-30"> | |
| <h3 class="text-xl text-cyan-300 font-bold mb-2">Stats</h3> | |
| <div class="flex items-center justify-between mb-2"> | |
| <span class="text-purple-300">Score:</span> | |
| <span id="score" class="text-cyan-300 font-bold">0</span> | |
| </div> | |
| <div class="flex items-center justify-between mb-2"> | |
| <span class="text-purple-300">Speed:</span> | |
| <span id="speed" class="text-cyan-300 font-bold">1x</span> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <span class="text-purple-300">Length:</span> | |
| <span id="length" class="text-cyan-300 font-bold">3</span> | |
| </div> | |
| </div> | |
| <div class="flex flex-col gap-2"> | |
| <button id="pause-btn" class="neon-btn bg-purple-600 hover:bg-purple-500 text-white font-bold py-2 px-4 rounded-full flex items-center justify-center"> | |
| <i class="fas fa-pause mr-2"></i> Pause | |
| </button> | |
| <button id="sound-btn" class="neon-btn bg-blue-600 hover:bg-blue-500 text-white font-bold py-2 px-4 rounded-full flex items-center justify-center"> | |
| <i class="fas fa-volume-up mr-2"></i> Sound On | |
| </button> | |
| </div> | |
| </div> | |
| <div class="mt-8 text-gray-400 text-sm"> | |
| <p>Use arrow keys or on-screen controls to move the snake</p> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Game constants | |
| const GRID_SIZE = 20; | |
| const CELL_SIZE = 20; | |
| const INITIAL_SPEED = 150; | |
| const SPEED_INCREMENT = 5; | |
| // Game variables | |
| let snake = [{x: 10, y: 10}]; | |
| let food = generateFood(); | |
| let direction = 'right'; | |
| let nextDirection = 'right'; | |
| let gameInterval; | |
| let score = 0; | |
| let speed = INITIAL_SPEED; | |
| let gameRunning = false; | |
| let soundEnabled = true; | |
| let gamePaused = false; | |
| // DOM elements | |
| const gameBoard = document.getElementById('game-board'); | |
| const scoreElement = document.getElementById('score'); | |
| const lengthElement = document.getElementById('length'); | |
| const speedElement = document.getElementById('speed'); | |
| const gameOverlay = document.getElementById('game-overlay'); | |
| const finalScoreElement = document.getElementById('final-score'); | |
| const restartBtn = document.getElementById('restart-btn'); | |
| const pauseBtn = document.getElementById('pause-btn'); | |
| const soundBtn = document.getElementById('sound-btn'); | |
| const controlBtns = document.querySelectorAll('.control-btn'); | |
| // Initialize game board | |
| function initializeGameBoard() { | |
| gameBoard.innerHTML = ''; | |
| gameBoard.style.width = `${GRID_SIZE * CELL_SIZE}px`; | |
| gameBoard.style.height = `${GRID_SIZE * CELL_SIZE}px`; | |
| // Create grid cells | |
| for (let y = 0; y < GRID_SIZE; y++) { | |
| for (let x = 0; x < GRID_SIZE; x++) { | |
| const cell = document.createElement('div'); | |
| cell.className = 'grid-cell absolute'; | |
| cell.style.width = `${CELL_SIZE}px`; | |
| cell.style.height = `${CELL_SIZE}px`; | |
| cell.style.left = `${x * CELL_SIZE}px`; | |
| cell.style.top = `${y * CELL_SIZE}px`; | |
| cell.dataset.x = x; | |
| cell.dataset.y = y; | |
| gameBoard.appendChild(cell); | |
| } | |
| } | |
| // Add grid pattern overlay | |
| for (let i = 0; i < GRID_SIZE; i++) { | |
| const lineH = document.createElement('div'); | |
| lineH.className = 'absolute bg-gray-800 opacity-10'; | |
| lineH.style.width = '100%'; | |
| lineH.style.height = '1px'; | |
| lineH.style.top = `${i * CELL_SIZE}px`; | |
| lineH.style.left = '0'; | |
| const lineV = document.createElement('div'); | |
| lineV.className = 'absolute bg-gray-800 opacity-10'; | |
| lineV.style.width = '1px'; | |
| lineV.style.height = '100%'; | |
| lineV.style.left = `${i * CELL_SIZE}px`; | |
| lineV.style.top = '0'; | |
| gameBoard.appendChild(lineH); | |
| gameBoard.appendChild(lineV); | |
| } | |
| } | |
| // Generate food at random position | |
| function generateFood() { | |
| let newFood; | |
| do { | |
| newFood = { | |
| x: Math.floor(Math.random() * GRID_SIZE), | |
| y: Math.floor(Math.random() * GRID_SIZE) | |
| }; | |
| } while (snake.some(segment => segment.x === newFood.x && segment.y === newFood.y)); | |
| return newFood; | |
| } | |
| // Update game state | |
| function updateGame() { | |
| if (gamePaused) return; | |
| // Update direction | |
| direction = nextDirection; | |
| // Move snake | |
| const head = {...snake[0]}; | |
| switch (direction) { | |
| case 'up': | |
| head.y--; | |
| break; | |
| case 'down': | |
| head.y++; | |
| break; | |
| case 'left': | |
| head.x--; | |
| break; | |
| case 'right': | |
| head.x++; | |
| break; | |
| } | |
| // Check for collisions | |
| if ( | |
| head.x < 0 || head.x >= GRID_SIZE || | |
| head.y < 0 || head.y >= GRID_SIZE || | |
| snake.some(segment => segment.x === head.x && segment.y === head.y) | |
| ) { | |
| gameOver(); | |
| return; | |
| } | |
| // Add new head | |
| snake.unshift(head); | |
| // Check for food | |
| if (head.x === food.x && head.y === food.y) { | |
| // Increase score | |
| score += 10; | |
| scoreElement.textContent = score; | |
| finalScoreElement.textContent = score; | |
| // Update length | |
| lengthElement.textContent = snake.length; | |
| // Increase speed | |
| speed = Math.max(50, speed - SPEED_INCREMENT); | |
| clearInterval(gameInterval); | |
| gameInterval = setInterval(updateGame, speed); | |
| speedElement.textContent = (INITIAL_SPEED / speed).toFixed(1) + 'x'; | |
| // Generate new food | |
| food = generateFood(); | |
| // Create particles | |
| createParticles(head.x * CELL_SIZE + CELL_SIZE/2, head.y * CELL_SIZE + CELL_SIZE/2, 10); | |
| // Play sound if enabled | |
| if (soundEnabled) { | |
| playEatSound(); | |
| } | |
| } else { | |
| // Remove tail if no food eaten | |
| snake.pop(); | |
| } | |
| // Render game | |
| renderGame(); | |
| } | |
| // Render game | |
| function renderGame() { | |
| // Clear all cells | |
| document.querySelectorAll('.grid-cell').forEach(cell => { | |
| cell.className = 'grid-cell absolute'; | |
| cell.style.width = `${CELL_SIZE}px`; | |
| cell.style.height = `${CELL_SIZE}px`; | |
| }); | |
| // Render snake | |
| snake.forEach((segment, index) => { | |
| const cell = document.querySelector(`.grid-cell[data-x="${segment.x}"][data-y="${segment.y}"]`); | |
| if (cell) { | |
| if (index === 0) { | |
| cell.classList.add('snake-head'); | |
| } else { | |
| cell.classList.add('snake-body'); | |
| } | |
| } | |
| }); | |
| // Render food | |
| const foodCell = document.querySelector(`.grid-cell[data-x="${food.x}"][data-y="${food.y}"]`); | |
| if (foodCell) { | |
| foodCell.classList.add('food'); | |
| } | |
| } | |
| // Game over | |
| function gameOver() { | |
| clearInterval(gameInterval); | |
| gameRunning = false; | |
| gameOverlay.classList.remove('hidden'); | |
| // Play sound if enabled | |
| if (soundEnabled) { | |
| playGameOverSound(); | |
| } | |
| } | |
| // Start new game | |
| function startGame() { | |
| // Reset game state | |
| snake = [{x: 10, y: 10}]; | |
| food = generateFood(); | |
| direction = 'right'; | |
| nextDirection = 'right'; | |
| score = 0; | |
| speed = INITIAL_SPEED; | |
| gameRunning = true; | |
| gamePaused = false; | |
| // Update UI | |
| scoreElement.textContent = score; | |
| lengthElement.textContent = snake.length; | |
| speedElement.textContent = '1x'; | |
| gameOverlay.classList.add('hidden'); | |
| pauseBtn.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause'; | |
| // Start game loop | |
| clearInterval(gameInterval); | |
| gameInterval = setInterval(updateGame, speed); | |
| // Initial render | |
| renderGame(); | |
| } | |
| // Create particles effect | |
| function createParticles(x, y, count) { | |
| for (let i = 0; i < count; i++) { | |
| const particle = document.createElement('div'); | |
| particle.className = 'particle'; | |
| const size = Math.random() * 4 + 2; | |
| particle.style.width = `${size}px`; | |
| particle.style.height = `${size}px`; | |
| particle.style.left = `${x}px`; | |
| particle.style.top = `${y}px`; | |
| const angle = Math.random() * Math.PI * 2; | |
| const velocity = Math.random() * 3 + 2; | |
| const vx = Math.cos(angle) * velocity; | |
| const vy = Math.sin(angle) * velocity; | |
| gameBoard.appendChild(particle); | |
| let posX = x; | |
| let posY = y; | |
| let opacity = 1; | |
| const animate = () => { | |
| posX += vx; | |
| posY += vy; | |
| opacity -= 0.03; | |
| particle.style.left = `${posX}px`; | |
| particle.style.top = `${posY}px`; | |
| particle.style.opacity = opacity; | |
| if (opacity > 0) { | |
| requestAnimationFrame(animate); | |
| } else { | |
| particle.remove(); | |
| } | |
| }; | |
| requestAnimationFrame(animate); | |
| } | |
| } | |
| // Sound effects | |
| function playEatSound() { | |
| const audioContext = new (window.AudioContext || window.webkitAudioContext)(); | |
| const oscillator = audioContext.createOscillator(); | |
| const gainNode = audioContext.createGain(); | |
| oscillator.type = 'sine'; | |
| oscillator.frequency.value = 800; | |
| gainNode.gain.value = 0.2; | |
| oscillator.connect(gainNode); | |
| gainNode.connect(audioContext.destination); | |
| oscillator.start(); | |
| gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3); | |
| oscillator.stop(audioContext.currentTime + 0.3); | |
| } | |
| function playGameOverSound() { | |
| const audioContext = new (window.AudioContext || window.webkitAudioContext)(); | |
| const oscillator = audioContext.createOscillator(); | |
| const gainNode = audioContext.createGain(); | |
| oscillator.type = 'sine'; | |
| oscillator.frequency.value = 300; | |
| gainNode.gain.value = 0.3; | |
| oscillator.connect(gainNode); | |
| gainNode.connect(audioContext.destination); | |
| oscillator.start(); | |
| oscillator.frequency.exponentialRampToValueAtTime(100, audioContext.currentTime + 0.5); | |
| gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.5); | |
| oscillator.stop(audioContext.currentTime + 0.5); | |
| } | |
| // Event listeners | |
| document.addEventListener('keydown', (e) => { | |
| if (!gameRunning) return; | |
| switch (e.key) { | |
| case 'ArrowUp': | |
| if (direction !== 'down') nextDirection = 'up'; | |
| break; | |
| case 'ArrowDown': | |
| if (direction !== 'up') nextDirection = 'down'; | |
| break; | |
| case 'ArrowLeft': | |
| if (direction !== 'right') nextDirection = 'left'; | |
| break; | |
| case 'ArrowRight': | |
| if (direction !== 'left') nextDirection = 'right'; | |
| break; | |
| case ' ': | |
| togglePause(); | |
| break; | |
| } | |
| }); | |
| controlBtns.forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| if (!gameRunning) return; | |
| const icon = btn.querySelector('i'); | |
| if (icon.classList.contains('fa-arrow-up') && direction !== 'down') { | |
| nextDirection = 'up'; | |
| } else if (icon.classList.contains('fa-arrow-down') && direction !== 'up') { | |
| nextDirection = 'down'; | |
| } else if (icon.classList.contains('fa-arrow-left') && direction !== 'right') { | |
| nextDirection = 'left'; | |
| } else if (icon.classList.contains('fa-arrow-right') && direction !== 'left') { | |
| nextDirection = 'right'; | |
| } | |
| }); | |
| }); | |
| restartBtn.addEventListener('click', startGame); | |
| pauseBtn.addEventListener('click', togglePause); | |
| function togglePause() { | |
| if (!gameRunning) return; | |
| gamePaused = !gamePaused; | |
| if (gamePaused) { | |
| pauseBtn.innerHTML = '<i class="fas fa-play mr-2"></i> Resume'; | |
| } else { | |
| pauseBtn.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause'; | |
| } | |
| } | |
| soundBtn.addEventListener('click', () => { | |
| soundEnabled = !soundEnabled; | |
| soundBtn.innerHTML = soundEnabled | |
| ? '<i class="fas fa-volume-up mr-2"></i> Sound On' | |
| : '<i class="fas fa-volume-mute mr-2"></i> Sound Off'; | |
| }); | |
| // Initialize game | |
| initializeGameBoard(); | |
| startGame(); | |
| }); | |
| </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=hythyt/test-sanke" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |