neonsnake / index.html
chakkale's picture
Add 3 files
4a3a9fd verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neon Cyberpunk Snake</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
body {
background-color: #0f0f1a;
font-family: 'Press Start 2P', cursive;
overflow: hidden;
color: #00f7ff;
}
.game-container {
position: relative;
border: 4px solid #ff00f7;
box-shadow: 0 0 20px #ff00f7,
inset 0 0 20px #ff00f7;
border-radius: 5px;
}
.snake {
background-color: #00f7ff;
box-shadow: 0 0 10px #00f7ff;
border-radius: 2px;
}
.food {
background-color: #ff00f7;
box-shadow: 0 0 10px #ff00f7;
border-radius: 50%;
animation: pulse 0.5s infinite alternate;
}
@keyframes pulse {
0% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.2);
opacity: 0.8;
}
}
.neon-text {
text-shadow: 0 0 5px #00f7ff,
0 0 10px #00f7ff,
0 0 15px #00f7ff;
}
.neon-pink {
text-shadow: 0 0 5px #ff00f7,
0 0 10px #ff00f7,
0 0 15px #ff00f7;
}
.grid-line {
border: 1px solid rgba(0, 247, 255, 0.1);
}
.scanline {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom,
rgba(0, 247, 255, 0) 0%,
rgba(0, 247, 255, 0.1) 50%,
rgba(0, 247, 255, 0) 100%);
background-size: 100% 8px;
pointer-events: none;
animation: scan 3s linear infinite;
}
@keyframes scan {
0% {
background-position: 0 0;
}
100% {
background-position: 0 100%;
}
}
.glitch {
position: relative;
}
.glitch::before, .glitch::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0f0f1a;
}
.glitch::before {
left: 2px;
text-shadow: -2px 0 #ff00f7;
clip-path: polygon(0 20%, 100% 20%, 100% 30%, 0 30%);
animation: glitch-anim 2s infinite linear alternate-reverse;
}
.glitch::after {
left: -2px;
text-shadow: 2px 0 #00f7ff;
clip-path: polygon(0 60%, 100% 60%, 100% 70%, 0 70%);
animation: glitch-anim 1.5s infinite linear alternate-reverse;
}
@keyframes glitch-anim {
0% {
transform: translate(0);
}
20% {
transform: translate(-3px, 3px);
}
40% {
transform: translate(-3px, -3px);
}
60% {
transform: translate(3px, 3px);
}
80% {
transform: translate(3px, -3px);
}
100% {
transform: translate(0);
}
}
.btn-neon {
background: transparent;
border: 2px solid #00f7ff;
color: #00f7ff;
padding: 10px 20px;
font-family: 'Press Start 2P', cursive;
font-size: 12px;
cursor: pointer;
transition: all 0.3s;
box-shadow: 0 0 10px #00f7ff;
position: relative;
overflow: hidden;
}
.btn-neon:hover {
background: #00f7ff;
color: #0f0f1a;
box-shadow: 0 0 20px #00f7ff;
}
.btn-neon::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(0, 247, 255, 0.4), transparent);
transition: 0.5s;
}
.btn-neon:hover::before {
left: 100%;
}
</style>
</head>
<body class="min-h-screen flex flex-col items-center justify-center p-4">
<div class="text-center mb-6">
<h1 class="glitch neon-text text-4xl md:text-5xl mb-2" data-text="NEON SNAKE">NEON SNAKE</h1>
<p class="neon-pink text-sm">CYBERPUNK EDITION</p>
</div>
<div class="relative">
<div class="game-container">
<canvas id="gameCanvas" class="bg-black"></canvas>
<div class="scanline"></div>
</div>
<div id="gameOver" class="hidden absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-80">
<h2 class="neon-text text-3xl mb-6">GAME OVER</h2>
<p id="finalScore" class="neon-pink text-xl mb-6">SCORE: 0</p>
<button id="restartBtn" class="btn-neon">RESTART</button>
</div>
<div id="startScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-80">
<h2 class="neon-text text-3xl mb-6">NEON SNAKE</h2>
<p class="neon-pink text-sm mb-8">USE ARROW KEYS TO MOVE</p>
<button id="startBtn" class="btn-neon">START GAME</button>
</div>
</div>
<div class="mt-6 flex justify-between w-full max-w-md">
<div class="text-center">
<p class="neon-text text-sm">SCORE</p>
<p id="score" class="neon-pink text-2xl">0</p>
</div>
<div class="text-center">
<p class="neon-text text-sm">HIGH SCORE</p>
<p id="highScore" class="neon-pink text-2xl">0</p>
</div>
</div>
<div class="mt-6 grid grid-cols-4 gap-4">
<button id="upBtn" class="btn-neon py-2"></button>
<button id="leftBtn" class="btn-neon py-2"></button>
<button id="downBtn" class="btn-neon py-2"></button>
<button id="rightBtn" class="btn-neon py-2"></button>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startScreen = document.getElementById('startScreen');
const gameOverScreen = document.getElementById('gameOver');
const startBtn = document.getElementById('startBtn');
const restartBtn = document.getElementById('restartBtn');
const scoreDisplay = document.getElementById('score');
const highScoreDisplay = document.getElementById('highScore');
const finalScoreDisplay = document.getElementById('finalScore');
// Mobile controls
const upBtn = document.getElementById('upBtn');
const downBtn = document.getElementById('downBtn');
const leftBtn = document.getElementById('leftBtn');
const rightBtn = document.getElementById('rightBtn');
// Game settings
const gridSize = 20;
const tileCount = 20;
let speed = 7;
// Game state
let snake = [];
let food = {};
let direction = 'right';
let nextDirection = 'right';
let score = 0;
let highScore = localStorage.getItem('highScore') || 0;
let gameRunning = false;
let gameLoop;
// Set canvas size
canvas.width = gridSize * tileCount;
canvas.height = gridSize * tileCount;
// Initialize game
function initGame() {
snake = [
{x: 10, y: 10},
{x: 9, y: 10},
{x: 8, y: 10}
];
spawnFood();
direction = 'right';
nextDirection = 'right';
score = 0;
scoreDisplay.textContent = score;
highScoreDisplay.textContent = highScore;
gameRunning = true;
}
// Spawn food at random position
function spawnFood() {
food = {
x: Math.floor(Math.random() * tileCount),
y: Math.floor(Math.random() * tileCount)
};
// Make sure food doesn't spawn on snake
for (let segment of snake) {
if (segment.x === food.x && segment.y === food.y) {
return spawnFood();
}
}
}
// Main game loop
function gameUpdate() {
// Move snake
const head = {x: snake[0].x, y: snake[0].y};
direction = nextDirection;
switch(direction) {
case 'up':
head.y--;
break;
case 'down':
head.y++;
break;
case 'left':
head.x--;
break;
case 'right':
head.x++;
break;
}
// Check collision with walls
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
gameOver();
return;
}
// Check collision with self
for (let i = 0; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
gameOver();
return;
}
}
// Check if snake ate food
if (head.x === food.x && head.y === food.y) {
// Don't remove tail
score++;
scoreDisplay.textContent = score;
// Increase speed every 5 points
if (score % 5 === 0) {
speed += 0.5;
}
spawnFood();
} else {
// Remove tail
snake.pop();
}
// Add new head
snake.unshift(head);
// Draw everything
draw();
}
// Draw game
function draw() {
// Clear canvas
ctx.fillStyle = '#0f0f1a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw grid
ctx.strokeStyle = 'rgba(0, 247, 255, 0.1)';
ctx.lineWidth = 1;
for (let i = 0; i < tileCount; i++) {
// Vertical lines
ctx.beginPath();
ctx.moveTo(i * gridSize, 0);
ctx.lineTo(i * gridSize, canvas.height);
ctx.stroke();
// Horizontal lines
ctx.beginPath();
ctx.moveTo(0, i * gridSize);
ctx.lineTo(canvas.width, i * gridSize);
ctx.stroke();
}
// Draw snake
for (let segment of snake) {
ctx.fillStyle = '#00f7ff';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
// Add glow effect
ctx.shadowColor = '#00f7ff';
ctx.shadowBlur = 10;
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
ctx.shadowBlur = 0;
}
// Draw head with different color
const head = snake[0];
ctx.fillStyle = '#00ffaa';
ctx.fillRect(head.x * gridSize, head.y * gridSize, gridSize, gridSize);
ctx.shadowColor = '#00ffaa';
ctx.shadowBlur = 15;
ctx.fillRect(head.x * gridSize, head.y * gridSize, gridSize, gridSize);
ctx.shadowBlur = 0;
// Draw food
ctx.fillStyle = '#ff00f7';
ctx.beginPath();
ctx.arc(
food.x * gridSize + gridSize / 2,
food.y * gridSize + gridSize / 2,
gridSize / 2,
0,
Math.PI * 2
);
ctx.fill();
// Add glow effect
ctx.shadowColor = '#ff00f7';
ctx.shadowBlur = 15;
ctx.fill();
ctx.shadowBlur = 0;
}
// Game over
function gameOver() {
gameRunning = false;
clearInterval(gameLoop);
// Update high score
if (score > highScore) {
highScore = score;
localStorage.setItem('highScore', highScore);
highScoreDisplay.textContent = highScore;
}
finalScoreDisplay.textContent = `SCORE: ${score}`;
gameOverScreen.classList.remove('hidden');
}
// Start game
function startGame() {
startScreen.classList.add('hidden');
gameOverScreen.classList.add('hidden');
initGame();
draw();
gameLoop = setInterval(gameUpdate, 1000 / speed);
}
// Event listeners
startBtn.addEventListener('click', startGame);
restartBtn.addEventListener('click', startGame);
// Keyboard controls
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;
}
});
// Mobile controls
upBtn.addEventListener('click', () => {
if (gameRunning && direction !== 'down') nextDirection = 'up';
});
downBtn.addEventListener('click', () => {
if (gameRunning && direction !== 'up') nextDirection = 'down';
});
leftBtn.addEventListener('click', () => {
if (gameRunning && direction !== 'right') nextDirection = 'left';
});
rightBtn.addEventListener('click', () => {
if (gameRunning && direction !== 'left') nextDirection = 'right';
});
// Initial draw
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=chakkale/neonsnake" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>