| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Neon Grid Runner - Futuristic Fun 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;900&display=swap'); |
| |
| :root { |
| --neon-pink: #ff2d75; |
| --neon-blue: #0ff0fc; |
| --neon-purple: #9d00ff; |
| --neon-green: #00ff7f; |
| } |
| |
| body { |
| font-family: 'Orbitron', sans-serif; |
| background-color: #0a0a1a; |
| color: white; |
| overflow: hidden; |
| touch-action: manipulation; |
| } |
| |
| .neon-text-pink { |
| text-shadow: 0 0 10px var(--neon-pink), 0 0 20px var(--neon-pink); |
| color: var(--neon-pink); |
| } |
| |
| .neon-text-blue { |
| text-shadow: 0 0 10px var(--neon-blue), 0 0 20px var(--neon-blue); |
| color: var(--neon-blue); |
| } |
| |
| .neon-border-pink { |
| box-shadow: 0 0 10px var(--neon-pink), 0 0 20px var(--neon-pink); |
| border: 2px solid var(--neon-pink); |
| } |
| |
| .neon-border-blue { |
| box-shadow: 0 0 10px var(--neon-blue), 0 0 20px var(--neon-blue); |
| border: 2px solid var(--neon-blue); |
| } |
| |
| .grid-cell { |
| transition: all 0.3s ease; |
| } |
| |
| .grid-cell.active { |
| background-color: var(--neon-blue); |
| box-shadow: 0 0 15px var(--neon-blue); |
| } |
| |
| .grid-cell.target { |
| background-color: var(--neon-pink); |
| box-shadow: 0 0 15px var(--neon-pink); |
| animation: pulse 1s infinite; |
| } |
| |
| .player { |
| background-color: var(--neon-green); |
| box-shadow: 0 0 15px var(--neon-green); |
| border-radius: 50%; |
| z-index: 10; |
| } |
| |
| @keyframes pulse { |
| 0% { transform: scale(1); } |
| 50% { transform: scale(1.1); } |
| 100% { transform: scale(1); } |
| } |
| |
| .cyber-btn { |
| position: relative; |
| overflow: hidden; |
| transition: all 0.3s; |
| } |
| |
| .cyber-btn:hover { |
| transform: translateY(-3px); |
| } |
| |
| .cyber-btn::before { |
| content: ''; |
| position: absolute; |
| top: 0; |
| left: -100%; |
| width: 100%; |
| height: 100%; |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); |
| transition: all 0.5s; |
| } |
| |
| .cyber-btn:hover::before { |
| left: 100%; |
| } |
| |
| .particle { |
| position: absolute; |
| background-color: var(--neon-purple); |
| border-radius: 50%; |
| pointer-events: none; |
| } |
| |
| .glow { |
| filter: drop-shadow(0 0 8px currentColor); |
| } |
| |
| .keyboard-hint { |
| position: fixed; |
| bottom: 20px; |
| left: 50%; |
| transform: translateX(-50%); |
| background: rgba(0, 0, 0, 0.7); |
| padding: 10px 20px; |
| border-radius: 20px; |
| border: 1px solid var(--neon-blue); |
| box-shadow: 0 0 10px var(--neon-blue); |
| display: flex; |
| gap: 15px; |
| align-items: center; |
| z-index: 100; |
| } |
| |
| .key { |
| background: rgba(0, 0, 0, 0.8); |
| border: 1px solid var(--neon-blue); |
| color: var(--neon-blue); |
| padding: 5px 10px; |
| border-radius: 5px; |
| font-family: monospace; |
| font-weight: bold; |
| box-shadow: 0 0 5px var(--neon-blue); |
| } |
| |
| .keyboard-hint-text { |
| color: var(--neon-blue); |
| font-size: 0.9rem; |
| } |
| |
| @media (max-width: 768px) { |
| .keyboard-hint { |
| display: none; |
| } |
| } |
| </style> |
| </head> |
| <body class="h-screen flex flex-col"> |
| |
| <div id="particles-container" class="absolute w-full h-full overflow-hidden"></div> |
| |
| |
| <div class="container mx-auto flex-1 flex flex-col items-center justify-center relative z-10 p-4"> |
| |
| <header class="text-center mb-8"> |
| <h1 class="text-5xl md:text-6xl font-bold neon-text-pink mb-2">NEON GRID RUNNER</h1> |
| <p class="text-xl neon-text-blue">Navigate the cyber grid to reach the target</p> |
| </header> |
| |
| |
| <div class="flex justify-between w-full max-w-md mb-6"> |
| <div class="text-center neon-text-blue"> |
| <p class="text-sm uppercase tracking-widest">Level</p> |
| <p class="text-3xl font-bold" id="level">1</p> |
| </div> |
| <div class="text-center neon-text-pink"> |
| <p class="text-sm uppercase tracking-widest">Score</p> |
| <p class="text-3xl font-bold" id="score">0</p> |
| </div> |
| <div class="text-center neon-text-blue"> |
| <p class="text-sm uppercase tracking-widest">Time</p> |
| <p class="text-3xl font-bold" id="time">60</p> |
| </div> |
| </div> |
| |
| |
| <div class="relative"> |
| <div id="game-grid" class="grid gap-1 bg-black bg-opacity-30 p-2 neon-border-blue rounded-lg"></div> |
| <div id="player" class="player absolute transition-all duration-300"></div> |
| </div> |
| |
| |
| <div class="mt-8 flex flex-col items-center"> |
| <div class="grid grid-cols-3 gap-2 mb-4"> |
| <button class="cyber-btn bg-gray-900 text-white w-12 h-12 flex items-center justify-center neon-border-blue rounded" id="up"> |
| <i class="fas fa-arrow-up glow text-blue-400"></i> |
| </button> |
| <div></div> |
| <div></div> |
| <button class="cyber-btn bg-gray-900 text-white w-12 h-12 flex items-center justify-center neon-border-blue rounded" id="left"> |
| <i class="fas fa-arrow-left glow text-blue-400"></i> |
| </button> |
| <button class="cyber-btn bg-gray-900 text-white w-12 h-12 flex items-center justify-center neon-border-blue rounded" id="down"> |
| <i class="fas fa-arrow-down glow text-blue-400"></i> |
| </button> |
| <button class="cyber-btn bg-gray-900 text-white w-12 h-12 flex items-center justify-center neon-border-blue rounded" id="right"> |
| <i class="fas fa-arrow-right glow text-blue-400"></i> |
| </button> |
| </div> |
| |
| <div class="flex gap-4"> |
| <button id="start-btn" class="cyber-btn bg-gradient-to-r from-purple-600 to-pink-600 text-white px-6 py-3 rounded-full font-bold uppercase tracking-wider neon-border-pink"> |
| Start Game |
| </button> |
| <button id="reset-btn" class="cyber-btn bg-gray-900 text-white px-6 py-3 rounded-full font-bold uppercase tracking-wider neon-border-blue"> |
| Reset |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="keyboard-hint"> |
| <span class="keyboard-hint-text">Use keyboard:</span> |
| <span class="key">↑</span> |
| <span class="key">↓</span> |
| <span class="key">←</span> |
| <span class="key">→</span> |
| <span class="keyboard-hint-text">to move</span> |
| </div> |
| |
| |
| <div id="game-over-modal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-20 hidden"> |
| <div class="bg-gray-900 neon-border-pink rounded-xl p-8 max-w-md w-full mx-4 text-center"> |
| <h2 class="text-4xl font-bold neon-text-pink mb-4">GAME OVER</h2> |
| <p class="text-xl neon-text-blue mb-2">Your final score: <span id="final-score" class="font-bold">0</span></p> |
| <p class="text-lg neon-text-blue mb-6">Level reached: <span id="final-level" class="font-bold">1</span></p> |
| <button id="play-again-btn" class="cyber-btn bg-gradient-to-r from-blue-600 to-purple-600 text-white px-6 py-3 rounded-full font-bold uppercase tracking-wider neon-border-blue w-full"> |
| Play Again |
| </button> |
| </div> |
| </div> |
| |
| |
| <audio id="move-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-arcade-game-jump-coin-216.mp3" preload="auto"></audio> |
| <audio id="target-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-winning-chimes-2015.mp3" preload="auto"></audio> |
| <audio id="game-over-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-retro-arcade-lose-2027.mp3" preload="auto"></audio> |
| |
| <script> |
| |
| const config = { |
| gridSize: 8, |
| cellSize: 50, |
| playerSize: 40, |
| initialTime: 60, |
| levelUpScore: 5, |
| timeBonus: 15, |
| moveCooldown: 150 |
| }; |
| |
| |
| let state = { |
| score: 0, |
| level: 1, |
| timeLeft: config.initialTime, |
| playerPos: { x: 0, y: 0 }, |
| targetPos: { x: 0, y: 0 }, |
| gameActive: false, |
| timer: null, |
| moveCount: 0, |
| lastMoveTime: 0, |
| keysPressed: { |
| ArrowUp: false, |
| ArrowDown: false, |
| ArrowLeft: false, |
| ArrowRight: false |
| } |
| }; |
| |
| |
| const gameGrid = document.getElementById('game-grid'); |
| const player = document.getElementById('player'); |
| const scoreElement = document.getElementById('score'); |
| const levelElement = document.getElementById('level'); |
| const timeElement = document.getElementById('time'); |
| const startBtn = document.getElementById('start-btn'); |
| const resetBtn = document.getElementById('reset-btn'); |
| const gameOverModal = document.getElementById('game-over-modal'); |
| const finalScoreElement = document.getElementById('final-score'); |
| const finalLevelElement = document.getElementById('final-level'); |
| const playAgainBtn = document.getElementById('play-again-btn'); |
| const particlesContainer = document.getElementById('particles-container'); |
| |
| |
| const moveSound = document.getElementById('move-sound'); |
| const targetSound = document.getElementById('target-sound'); |
| const gameOverSound = document.getElementById('game-over-sound'); |
| |
| |
| function initGame() { |
| |
| gameGrid.innerHTML = ''; |
| gameGrid.style.gridTemplateColumns = `repeat(${config.gridSize}, ${config.cellSize}px)`; |
| gameGrid.style.gridTemplateRows = `repeat(${config.gridSize}, ${config.cellSize}px)`; |
| |
| for (let y = 0; y < config.gridSize; y++) { |
| for (let x = 0; x < config.gridSize; x++) { |
| const cell = document.createElement('div'); |
| cell.className = 'grid-cell bg-gray-800 bg-opacity-50'; |
| cell.dataset.x = x; |
| cell.dataset.y = y; |
| gameGrid.appendChild(cell); |
| } |
| } |
| |
| |
| player.style.width = `${config.playerSize}px`; |
| player.style.height = `${config.playerSize}px`; |
| |
| |
| state.score = 0; |
| state.level = 1; |
| state.timeLeft = config.initialTime; |
| state.moveCount = 0; |
| state.gameActive = false; |
| state.lastMoveTime = 0; |
| state.keysPressed = { |
| ArrowUp: false, |
| ArrowDown: false, |
| ArrowLeft: false, |
| ArrowRight: false |
| }; |
| |
| |
| updateUI(); |
| |
| |
| placePlayer(); |
| placeTarget(); |
| } |
| |
| |
| function placePlayer() { |
| state.playerPos = { |
| x: Math.floor(Math.random() * config.gridSize), |
| y: Math.floor(Math.random() * config.gridSize) |
| }; |
| updatePlayerPosition(); |
| } |
| |
| |
| function placeTarget() { |
| let newX, newY; |
| do { |
| newX = Math.floor(Math.random() * config.gridSize); |
| newY = Math.floor(Math.random() * config.gridSize); |
| } while (newX === state.playerPos.x && newY === state.playerPos.y); |
| |
| state.targetPos = { x: newX, y: newY }; |
| |
| |
| document.querySelectorAll('.grid-cell').forEach(cell => { |
| cell.classList.remove('target'); |
| }); |
| |
| const targetCell = document.querySelector(`.grid-cell[data-x="${state.targetPos.x}"][data-y="${state.targetPos.y}"]`); |
| if (targetCell) { |
| targetCell.classList.add('target'); |
| } |
| } |
| |
| |
| function updatePlayerPosition() { |
| const x = state.playerPos.x * config.cellSize + (config.cellSize - config.playerSize) / 2; |
| const y = state.playerPos.y * config.cellSize + (config.cellSize - config.playerSize) / 2; |
| |
| player.style.transform = `translate(${x}px, ${y}px)`; |
| |
| |
| document.querySelectorAll('.grid-cell').forEach(cell => { |
| cell.classList.remove('active'); |
| }); |
| |
| const currentCell = document.querySelector(`.grid-cell[data-x="${state.playerPos.x}"][data-y="${state.playerPos.y}"]`); |
| if (currentCell) { |
| currentCell.classList.add('active'); |
| } |
| } |
| |
| |
| function movePlayer(direction) { |
| if (!state.gameActive) return; |
| |
| const now = Date.now(); |
| if (now - state.lastMoveTime < config.moveCooldown) return; |
| |
| state.lastMoveTime = now; |
| |
| let newX = state.playerPos.x; |
| let newY = state.playerPos.y; |
| |
| switch (direction) { |
| case 'up': |
| newY = Math.max(0, state.playerPos.y - 1); |
| break; |
| case 'down': |
| newY = Math.min(config.gridSize - 1, state.playerPos.y + 1); |
| break; |
| case 'left': |
| newX = Math.max(0, state.playerPos.x - 1); |
| break; |
| case 'right': |
| newX = Math.min(config.gridSize - 1, state.playerPos.x + 1); |
| break; |
| } |
| |
| |
| if (newX !== state.playerPos.x || newY !== state.playerPos.y) { |
| state.playerPos = { x: newX, y: newY }; |
| state.moveCount++; |
| updatePlayerPosition(); |
| moveSound.currentTime = 0; |
| moveSound.play(); |
| createParticles(state.playerPos.x, state.playerPos.y, '#00ff7f'); |
| |
| |
| if (newX === state.targetPos.x && newY === state.targetPos.y) { |
| targetReached(); |
| } |
| } |
| } |
| |
| |
| function targetReached() { |
| state.score += state.level; |
| targetSound.currentTime = 0; |
| targetSound.play(); |
| createParticles(state.targetPos.x, state.targetPos.y, '#ff2d75', 30); |
| |
| |
| if (state.score >= state.level * config.levelUpScore) { |
| state.level++; |
| state.timeLeft += config.timeBonus; |
| createParticles(Math.floor(config.gridSize / 2), Math.floor(config.gridSize / 2), '#0ff0fc', 50); |
| } |
| |
| placeTarget(); |
| updateUI(); |
| } |
| |
| |
| function updateUI() { |
| scoreElement.textContent = state.score; |
| levelElement.textContent = state.level; |
| timeElement.textContent = state.timeLeft; |
| } |
| |
| |
| function startGame() { |
| if (state.gameActive) return; |
| |
| state.gameActive = true; |
| startBtn.textContent = 'Pause Game'; |
| |
| |
| state.timer = setInterval(() => { |
| state.timeLeft--; |
| updateUI(); |
| |
| if (state.timeLeft <= 0) { |
| endGame(); |
| } |
| }, 1000); |
| } |
| |
| |
| function pauseGame() { |
| state.gameActive = false; |
| clearInterval(state.timer); |
| startBtn.textContent = 'Resume Game'; |
| } |
| |
| |
| function endGame() { |
| state.gameActive = false; |
| clearInterval(state.timer); |
| |
| |
| finalScoreElement.textContent = state.score; |
| finalLevelElement.textContent = state.level; |
| gameOverModal.classList.remove('hidden'); |
| gameOverSound.play(); |
| |
| |
| for (let i = 0; i < 100; i++) { |
| setTimeout(() => { |
| createParticles( |
| Math.floor(Math.random() * config.gridSize), |
| Math.floor(Math.random() * config.gridSize), |
| ['#ff2d75', '#0ff0fc', '#9d00ff', '#00ff7f'][Math.floor(Math.random() * 4)], |
| 5 |
| ); |
| }, i * 30); |
| } |
| } |
| |
| |
| function resetGame() { |
| pauseGame(); |
| initGame(); |
| } |
| |
| |
| function createParticles(x, y, color, count = 10) { |
| const cellX = x * config.cellSize + (config.cellSize / 2); |
| const cellY = y * config.cellSize + (config.cellSize / 2); |
| |
| for (let i = 0; i < count; i++) { |
| const particle = document.createElement('div'); |
| particle.className = 'particle'; |
| particle.style.backgroundColor = color; |
| particle.style.width = `${Math.random() * 6 + 2}px`; |
| particle.style.height = particle.style.width; |
| particle.style.left = `${cellX}px`; |
| particle.style.top = `${cellY}px`; |
| |
| const angle = Math.random() * Math.PI * 2; |
| const velocity = Math.random() * 5 + 2; |
| const lifetime = Math.random() * 1000 + 500; |
| |
| particlesContainer.appendChild(particle); |
| |
| let startTime = Date.now(); |
| |
| const animate = () => { |
| const elapsed = Date.now() - startTime; |
| const progress = elapsed / lifetime; |
| |
| if (progress >= 1) { |
| particle.remove(); |
| return; |
| } |
| |
| const currentX = cellX + Math.cos(angle) * velocity * elapsed / 20; |
| const currentY = cellY + Math.sin(angle) * velocity * elapsed / 20; |
| |
| particle.style.opacity = 1 - progress; |
| particle.style.transform = `translate(${currentX}px, ${currentY}px)`; |
| |
| requestAnimationFrame(animate); |
| }; |
| |
| requestAnimationFrame(animate); |
| } |
| } |
| |
| |
| document.addEventListener('keydown', (e) => { |
| if (!state.gameActive) return; |
| |
| |
| if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) { |
| e.preventDefault(); |
| } |
| |
| |
| if (e.key in state.keysPressed) { |
| state.keysPressed[e.key] = true; |
| |
| |
| switch (e.key) { |
| case 'ArrowUp': |
| movePlayer('up'); |
| break; |
| case 'ArrowDown': |
| movePlayer('down'); |
| break; |
| case 'ArrowLeft': |
| movePlayer('left'); |
| break; |
| case 'ArrowRight': |
| movePlayer('right'); |
| break; |
| } |
| } |
| }); |
| |
| document.addEventListener('keyup', (e) => { |
| if (e.key in state.keysPressed) { |
| state.keysPressed[e.key] = false; |
| } |
| }); |
| |
| |
| function handleContinuousMovement() { |
| const now = Date.now(); |
| if (now - state.lastMoveTime >= config.moveCooldown) { |
| if (state.keysPressed.ArrowUp) movePlayer('up'); |
| if (state.keysPressed.ArrowDown) movePlayer('down'); |
| if (state.keysPressed.ArrowLeft) movePlayer('left'); |
| if (state.keysPressed.ArrowRight) movePlayer('right'); |
| } |
| requestAnimationFrame(handleContinuousMovement); |
| } |
| |
| |
| handleContinuousMovement(); |
| |
| |
| document.getElementById('up').addEventListener('click', () => movePlayer('up')); |
| document.getElementById('down').addEventListener('click', () => movePlayer('down')); |
| document.getElementById('left').addEventListener('click', () => movePlayer('left')); |
| document.getElementById('right').addEventListener('click', () => movePlayer('right')); |
| |
| |
| startBtn.addEventListener('click', () => { |
| if (state.gameActive) { |
| pauseGame(); |
| } else { |
| startGame(); |
| } |
| }); |
| |
| |
| resetBtn.addEventListener('click', resetGame); |
| |
| |
| playAgainBtn.addEventListener('click', () => { |
| gameOverModal.classList.add('hidden'); |
| resetGame(); |
| startGame(); |
| }); |
| |
| |
| window.addEventListener('load', initGame); |
| </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=zblaaa/tes-game" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |