File size: 17,493 Bytes
dd7ab0c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Snake Game</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        /* Custom styles for the game canvas */
        .game-container {
            position: relative;
            margin: 0 auto;
            border: 8px solid #4B5563;
            border-radius: 8px;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
        }
        
        canvas {
            display: block;
            background-color: #1F2937;
        }
        
        .game-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            background-color: rgba(0, 0, 0, 0.7);
            color: white;
            font-size: 2rem;
            z-index: 10;
        }
        
        .snake-cell {
            transition: all 0.1s ease;
        }
        
        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.1); }
            100% { transform: scale(1); }
        }
        
        .pulse {
            animation: pulse 0.5s infinite;
        }
    </style>
</head>
<body class="bg-gray-900 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-green-400 mb-2">🐍 Snake Game</h1>
        <p class="text-gray-300">Use arrow keys or swipe to control the snake</p>
    </div>
    
    <div class="game-container relative">
        <canvas id="gameCanvas" width="400" height="400"></canvas>
        
        <div id="gameOverlay" class="game-overlay hidden">
            <h2 class="text-4xl font-bold text-red-500 mb-4">Game Over!</h2>
            <p class="text-xl mb-6">Your score: <span id="finalScore" class="text-green-400 font-bold">0</span></p>
            <button id="restartBtn" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-6 rounded-full transition-all transform hover:scale-105">
                Play Again
            </button>
        </div>
        
        <div id="startScreen" class="game-overlay flex">
            <div class="text-center">
                <h2 class="text-4xl font-bold text-green-400 mb-6 pulse">Ready to Play?</h2>
                <button id="startBtn" class="bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-8 rounded-full text-xl transition-all transform hover:scale-105">
                    Start Game
                </button>
                <div class="mt-8 text-left text-gray-300">
                    <p class="flex items-center mb-2"><span class="inline-block w-6 mr-2">🔼</span> Move Up</p>
                    <p class="flex items-center mb-2"><span class="inline-block w-6 mr-2">🔽</span> Move Down</p>
                    <p class="flex items-center mb-2"><span class="inline-block w-6 mr-2">◀️</span> Move Left</p>
                    <p class="flex items-center"><span class="inline-block w-6 mr-2">▶️</span> Move Right</p>
                </div>
            </div>
        </div>
    </div>
    
    <div class="mt-6 flex justify-between w-full max-w-md">
        <div class="bg-gray-800 p-4 rounded-lg text-center flex-1 mx-2">
            <p class="text-gray-400">Score</p>
            <p id="score" class="text-2xl font-bold text-green-400">0</p>
        </div>
        <div class="bg-gray-800 p-4 rounded-lg text-center flex-1 mx-2">
            <p class="text-gray-400">High Score</p>
            <p id="highScore" class="text-2xl font-bold text-yellow-400">0</p>
        </div>
    </div>
    
    <div class="mt-8 grid grid-cols-4 gap-2 md:hidden">
        <button id="upBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-4 rounded-full transition-all"></button>
        <div class="col-span-2"></div>
        <button id="leftBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-4 rounded-full transition-all"></button>
        <button id="downBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-4 rounded-full transition-all"></button>
        <button id="rightBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-4 rounded-full transition-all"></button>
    </div>
    
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // Game variables
            const canvas = document.getElementById('gameCanvas');
            const ctx = canvas.getContext('2d');
            const scoreElement = document.getElementById('score');
            const highScoreElement = document.getElementById('highScore');
            const gameOverlay = document.getElementById('gameOverlay');
            const startScreen = document.getElementById('startScreen');
            const finalScoreElement = document.getElementById('finalScore');
            const restartBtn = document.getElementById('restartBtn');
            const startBtn = document.getElementById('startBtn');
            
            // 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 = canvas.width / gridSize;
            let speed = 7;
            
            // Game state
            let snake = [];
            let food = {};
            let direction = 'right';
            let nextDirection = 'right';
            let score = 0;
            let highScore = localStorage.getItem('snakeHighScore') || 0;
            let gameRunning = false;
            let gameLoop;
            
            // Initialize game
            highScoreElement.textContent = highScore;
            
            // Event listeners
            document.addEventListener('keydown', changeDirection);
            restartBtn.addEventListener('click', resetGame);
            startBtn.addEventListener('click', startGame);
            
            // Mobile controls
            upBtn.addEventListener('click', () => changeDirection({keyCode: 38}));
            downBtn.addEventListener('click', () => changeDirection({keyCode: 40}));
            leftBtn.addEventListener('click', () => changeDirection({keyCode: 37}));
            rightBtn.addEventListener('click', () => changeDirection({keyCode: 39}));
            
            // Touch controls for swipe
            let touchStartX = 0;
            let touchStartY = 0;
            
            canvas.addEventListener('touchstart', (e) => {
                touchStartX = e.touches[0].clientX;
                touchStartY = e.touches[0].clientY;
            }, false);
            
            canvas.addEventListener('touchmove', (e) => {
                if (!touchStartX || !touchStartY) return;
                
                const touchEndX = e.touches[0].clientX;
                const touchEndY = e.touches[0].clientY;
                
                const diffX = touchStartX - touchEndX;
                const diffY = touchStartY - touchEndY;
                
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    // Horizontal swipe
                    if (diffX > 0 && direction !== 'right') {
                        nextDirection = 'left';
                    } else if (diffX < 0 && direction !== 'left') {
                        nextDirection = 'right';
                    }
                } else {
                    // Vertical swipe
                    if (diffY > 0 && direction !== 'down') {
                        nextDirection = 'up';
                    } else if (diffY < 0 && direction !== 'up') {
                        nextDirection = 'down';
                    }
                }
                
                touchStartX = 0;
                touchStartY = 0;
                e.preventDefault();
            }, false);
            
            function startGame() {
                startScreen.classList.add('hidden');
                resetGame();
            }
            
            function resetGame() {
                // Reset snake
                snake = [];
                for (let i = 3; i >= 0; i--) {
                    snake.push({x: i, y: 0});
                }
                
                // Reset game state
                direction = 'right';
                nextDirection = 'right';
                score = 0;
                scoreElement.textContent = score;
                gameOverlay.classList.add('hidden');
                gameRunning = true;
                
                // Create first food
                createFood();
                
                // Start game loop
                if (gameLoop) clearInterval(gameLoop);
                gameLoop = setInterval(gameUpdate, 1000 / speed);
            }
            
            function gameUpdate() {
                // Update direction
                direction = nextDirection;
                
                // Move snake
                const head = {x: snake[0].x, y: snake[0].y};
                
                switch (direction) {
                    case 'up':
                        head.y--;
                        break;
                    case 'down':
                        head.y++;
                        break;
                    case 'left':
                        head.x--;
                        break;
                    case 'right':
                        head.x++;
                        break;
                }
                
                // Check wall collision
                if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
                    gameOver();
                    return;
                }
                
                // Check self collision
                for (let i = 0; i < snake.length; i++) {
                    if (snake[i].x === head.x && snake[i].y === head.y) {
                        gameOver();
                        return;
                    }
                }
                
                // Check food collision
                if (head.x === food.x && head.y === food.y) {
                    // Don't remove tail (snake grows)
                    createFood();
                    score++;
                    scoreElement.textContent = score;
                    
                    // Increase speed slightly every 5 points
                    if (score % 5 === 0) {
                        speed += 0.5;
                        clearInterval(gameLoop);
                        gameLoop = setInterval(gameUpdate, 1000 / speed);
                    }
                } else {
                    // Remove tail
                    snake.pop();
                }
                
                // Add new head
                snake.unshift(head);
                
                // Draw everything
                drawGame();
            }
            
            function drawGame() {
                // Clear canvas
                ctx.fillStyle = '#1F2937';
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                
                // Draw grid lines
                ctx.strokeStyle = '#374151';
                ctx.lineWidth = 0.5;
                
                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
                snake.forEach((segment, index) => {
                    // Head is different color
                    if (index === 0) {
                        ctx.fillStyle = '#10B981'; // Head color
                    } else {
                        // Gradient body color
                        const hue = 120 - (index * 2);
                        ctx.fillStyle = `hsl(${hue}, 80%, 50%)`;
                    }
                    
                    ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize - 1, gridSize - 1);
                    
                    // Add eyes to head
                    if (index === 0) {
                        ctx.fillStyle = 'white';
                        // Eye positions based on direction
                        if (direction === 'right') {
                            ctx.fillRect((segment.x * gridSize) + 12, (segment.y * gridSize) + 4, 4, 4);
                            ctx.fillRect((segment.x * gridSize) + 12, (segment.y * gridSize) + 12, 4, 4);
                        } else if (direction === 'left') {
                            ctx.fillRect((segment.x * gridSize) + 4, (segment.y * gridSize) + 4, 4, 4);
                            ctx.fillRect((segment.x * gridSize) + 4, (segment.y * gridSize) + 12, 4, 4);
                        } else if (direction === 'up') {
                            ctx.fillRect((segment.x * gridSize) + 4, (segment.y * gridSize) + 4, 4, 4);
                            ctx.fillRect((segment.x * gridSize) + 12, (segment.y * gridSize) + 4, 4, 4);
                        } else if (direction === 'down') {
                            ctx.fillRect((segment.x * gridSize) + 4, (segment.y * gridSize) + 12, 4, 4);
                            ctx.fillRect((segment.x * gridSize) + 12, (segment.y * gridSize) + 12, 4, 4);
                        }
                    }
                });
                
                // Draw food
                ctx.fillStyle = '#EF4444';
                ctx.beginPath();
                const centerX = (food.x * gridSize) + (gridSize / 2);
                const centerY = (food.y * gridSize) + (gridSize / 2);
                const radius = (gridSize / 2) - 2;
                ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
                ctx.fill();
                
                // Add shine to food
                ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
                ctx.beginPath();
                ctx.arc(centerX - 3, centerY - 3, 3, 0, Math.PI * 2);
                ctx.fill();
            }
            
            function createFood() {
                food = {
                    x: Math.floor(Math.random() * tileCount),
                    y: Math.floor(Math.random() * tileCount)
                };
                
                // Make sure food doesn't appear on snake
                for (let i = 0; i < snake.length; i++) {
                    if (snake[i].x === food.x && snake[i].y === food.y) {
                        createFood();
                        return;
                    }
                }
            }
            
            function changeDirection(e) {
                // Prevent opposite direction movement
                switch (e.keyCode) {
                    case 37: // Left
                        if (direction !== 'right') nextDirection = 'left';
                        break;
                    case 38: // Up
                        if (direction !== 'down') nextDirection = 'up';
                        break;
                    case 39: // Right
                        if (direction !== 'left') nextDirection = 'right';
                        break;
                    case 40: // Down
                        if (direction !== 'up') nextDirection = 'down';
                        break;
                }
            }
            
            function gameOver() {
                gameRunning = false;
                clearInterval(gameLoop);
                
                // Update high score
                if (score > highScore) {
                    highScore = score;
                    highScoreElement.textContent = highScore;
                    localStorage.setItem('snakeHighScore', highScore);
                }
                
                finalScoreElement.textContent = score;
                gameOverlay.classList.remove('hidden');
            }
            
            // Initial draw
            drawGame();
        });
    </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=Ibrokhim1263/https-huggingface-co-ibrokhim1263" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>