tes-game / index.html
zblaaa's picture
Add 2 files
086321d verified
Raw
History Blame Contribute Delete
24.6 kB
<!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">
<!-- Background Elements -->
<div id="particles-container" class="absolute w-full h-full overflow-hidden"></div>
<!-- Main Game Container -->
<div class="container mx-auto flex-1 flex flex-col items-center justify-center relative z-10 p-4">
<!-- Header -->
<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>
<!-- Game Stats -->
<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>
<!-- Game Grid -->
<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>
<!-- Controls -->
<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>
<!-- Keyboard Hint -->
<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>
<!-- Game Over Modal -->
<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 Elements -->
<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>
// Game Configuration
const config = {
gridSize: 8,
cellSize: 50,
playerSize: 40,
initialTime: 60,
levelUpScore: 5,
timeBonus: 15,
moveCooldown: 150 // milliseconds between moves
};
// Game State
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
}
};
// DOM Elements
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');
// Audio Elements
const moveSound = document.getElementById('move-sound');
const targetSound = document.getElementById('target-sound');
const gameOverSound = document.getElementById('game-over-sound');
// Initialize the game
function initGame() {
// Create grid cells
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);
}
}
// Set player size and initial position
player.style.width = `${config.playerSize}px`;
player.style.height = `${config.playerSize}px`;
// Reset game state
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
};
// Update UI
updateUI();
// Position player and target
placePlayer();
placeTarget();
}
// Place player at random position
function placePlayer() {
state.playerPos = {
x: Math.floor(Math.random() * config.gridSize),
y: Math.floor(Math.random() * config.gridSize)
};
updatePlayerPosition();
}
// Place target at random position (not same as player)
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 };
// Update target cell
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');
}
}
// Update player position on screen
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)`;
// Highlight current cell
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');
}
}
// Move player
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;
}
// Check if position changed
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');
// Check if reached target
if (newX === state.targetPos.x && newY === state.targetPos.y) {
targetReached();
}
}
}
// Target reached
function targetReached() {
state.score += state.level; // Higher levels give more points
targetSound.currentTime = 0;
targetSound.play();
createParticles(state.targetPos.x, state.targetPos.y, '#ff2d75', 30);
// Check for level up
if (state.score >= state.level * config.levelUpScore) {
state.level++;
state.timeLeft += config.timeBonus; // Time bonus for leveling up
createParticles(Math.floor(config.gridSize / 2), Math.floor(config.gridSize / 2), '#0ff0fc', 50);
}
placeTarget();
updateUI();
}
// Update UI elements
function updateUI() {
scoreElement.textContent = state.score;
levelElement.textContent = state.level;
timeElement.textContent = state.timeLeft;
}
// Start game
function startGame() {
if (state.gameActive) return;
state.gameActive = true;
startBtn.textContent = 'Pause Game';
// Start timer
state.timer = setInterval(() => {
state.timeLeft--;
updateUI();
if (state.timeLeft <= 0) {
endGame();
}
}, 1000);
}
// Pause game
function pauseGame() {
state.gameActive = false;
clearInterval(state.timer);
startBtn.textContent = 'Resume Game';
}
// End game
function endGame() {
state.gameActive = false;
clearInterval(state.timer);
// Show game over modal
finalScoreElement.textContent = state.score;
finalLevelElement.textContent = state.level;
gameOverModal.classList.remove('hidden');
gameOverSound.play();
// Create explosion effect
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);
}
}
// Reset game
function resetGame() {
pauseGame();
initGame();
}
// Create particles effect
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);
}
}
// Keyboard controls
document.addEventListener('keydown', (e) => {
if (!state.gameActive) return;
// Prevent default for arrow keys to avoid page scrolling
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
e.preventDefault();
}
// Track key state
if (e.key in state.keysPressed) {
state.keysPressed[e.key] = true;
// Execute move immediately on key press
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;
}
});
// Continuous movement when key is held down
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);
}
// Start continuous movement handler
handleContinuousMovement();
// Button controls
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'));
// Start/Pause button
startBtn.addEventListener('click', () => {
if (state.gameActive) {
pauseGame();
} else {
startGame();
}
});
// Reset button
resetBtn.addEventListener('click', resetGame);
// Play again button
playAgainBtn.addEventListener('click', () => {
gameOverModal.classList.add('hidden');
resetGame();
startGame();
});
// Initialize the game on load
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>