Mankeysocks commited on
Commit
26c1610
·
verified ·
1 Parent(s): 8ecfe5d

Create a mini-game inside GTA5 inspired by the classic Snake game, where players control a glowing digital "snake" using arrow keys. The twist: instead of collecting food, the snake navigates through an abstract virtual space shaped like a randomized keyboard key (e.g., "W", "E", "Shift", etc.), with the layout changing every time the game starts. Each round generates a unique glowing outline of a keyboard key using 3D shapes or Tron-style light paths. The snake must trace around the shape without colliding into itself or the boundaries. As the player progresses, the snake grows and the control sensitivity slightly increases, raising difficulty. The game is presented as a digital hacking side quest or arcade terminal in GTA5, possibly within a cybercafé or hidden hacker hideout. Visuals are neon-lit, synthwave-themed, with minimal UI and an immersive data-grid backdrop. Time challenges, score multipliers, and leaderboard integration keep replayability high. Optional integration allows players to earn small in-game cash or RP rewards based on performance. Ideal for both quick play and deeper mastery, it blends nostalgia with dynamic design in a modern GTA5 sandbox. - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +546 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Snker
3
- emoji: 🐠
4
- colorFrom: yellow
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: snker
3
+ emoji: 🐳
4
+ colorFrom: gray
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,546 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>GTA5 HACKER SNAKE</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
10
+
11
+ body {
12
+ font-family: 'Orbitron', sans-serif;
13
+ background-color: #0a0a1a;
14
+ overflow: hidden;
15
+ user-select: none;
16
+ }
17
+
18
+ #gameCanvas {
19
+ border: 2px solid rgba(0, 255, 255, 0.3);
20
+ box-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
21
+ }
22
+
23
+ .grid-bg {
24
+ position: absolute;
25
+ width: 100%;
26
+ height: 100%;
27
+ background:
28
+ linear-gradient(rgba(0, 255, 255, 0.1) 1px, transparent 1px),
29
+ linear-gradient(90deg, rgba(0, 255, 255, 0.1) 1px, transparent 1px);
30
+ background-size: 30px 30px;
31
+ z-index: -1;
32
+ }
33
+
34
+ .glow-text {
35
+ text-shadow: 0 0 10px cyan, 0 0 20px cyan;
36
+ }
37
+
38
+ .glow-box {
39
+ box-shadow: 0 0 15px cyan, inset 0 0 10px cyan;
40
+ }
41
+
42
+ .pulse {
43
+ animation: pulse 2s infinite;
44
+ }
45
+
46
+ @keyframes pulse {
47
+ 0% { opacity: 0.7; }
48
+ 50% { opacity: 1; }
49
+ 100% { opacity: 0.7; }
50
+ }
51
+
52
+ #keyOutline {
53
+ stroke-dasharray: 1000;
54
+ stroke-dashoffset: 1000;
55
+ animation: dash 5s linear forwards;
56
+ }
57
+
58
+ @keyframes dash {
59
+ to {
60
+ stroke-dashoffset: 0;
61
+ }
62
+ }
63
+ </style>
64
+ </head>
65
+ <body class="text-cyan-400 h-screen flex flex-col items-center justify-center relative">
66
+ <div class="grid-bg"></div>
67
+
68
+ <div class="absolute top-4 left-4 flex items-center gap-2">
69
+ <div class="w-3 h-3 rounded-full bg-red-500 animate-pulse"></div>
70
+ <span class="text-xs">LIVE FEED</span>
71
+ </div>
72
+
73
+ <div class="absolute top-4 right-4 text-xs">
74
+ <div class="flex gap-4">
75
+ <span>CONNECTION: <span class="text-green-500">SECURE</span></span>
76
+ <span>USER: <span class="text-cyan-300">PLAYER_1</span></span>
77
+ </div>
78
+ </div>
79
+
80
+ <h1 class="text-4xl font-bold mb-2 glow-text">// HACKER_SNAKE.EXE</h1>
81
+ <p class="text-xs mb-6 pulse">TRACE THE KEY PATTERN WITHOUT COLLISION</p>
82
+
83
+ <div class="relative">
84
+ <canvas id="gameCanvas" width="500" height="500" class="bg-black"></canvas>
85
+
86
+ <div id="startScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-80">
87
+ <h2 class="text-2xl mb-4 glow-text">GTA5 HACKING TERMINAL</h2>
88
+ <p class="text-sm mb-6 text-center px-8">Navigate the digital snake around the key outline<br>using arrow keys to complete the hack</p>
89
+ <button id="startBtn" class="px-6 py-2 bg-cyan-900 hover:bg-cyan-700 glow-box rounded-md font-bold transition-all">
90
+ INITIATE HACK
91
+ </button>
92
+ <div class="mt-6 text-xs">
93
+ <p>HIGH SCORE: <span id="highScoreDisplay">0</span></p>
94
+ <p>LAST SCORE: <span id="lastScoreDisplay">0</span></p>
95
+ </div>
96
+ </div>
97
+
98
+ <div id="gameOverScreen" class="absolute inset-0 hidden flex-col items-center justify-center bg-black bg-opacity-80">
99
+ <h2 class="text-2xl mb-2 glow-text">HACK TERMINATED</h2>
100
+ <p class="text-xl mb-2" id="finalScore">SCORE: 0</p>
101
+ <p class="text-sm mb-6" id="completionText">PARTIAL HACK COMPLETE</p>
102
+ <div class="flex gap-4">
103
+ <button id="restartBtn" class="px-4 py-2 bg-cyan-900 hover:bg-cyan-700 glow-box rounded-md font-bold transition-all">
104
+ RETRY
105
+ </button>
106
+ <button id="quitBtn" class="px-4 py-2 bg-purple-900 hover:bg-purple-700 glow-box rounded-md font-bold transition-all">
107
+ EXIT
108
+ </button>
109
+ </div>
110
+ </div>
111
+ </div>
112
+
113
+ <div class="mt-4 flex gap-8 text-sm">
114
+ <div>
115
+ <p>SCORE: <span id="scoreDisplay">0</span></p>
116
+ <p>TIME: <span id="timeDisplay">00:00</span></p>
117
+ </div>
118
+ <div>
119
+ <p>LEVEL: <span id="levelDisplay">1</span></p>
120
+ <p>MULTIPLIER: <span id="multiplierDisplay">1x</span></p>
121
+ </div>
122
+ </div>
123
+
124
+ <div class="absolute bottom-4 left-4 text-xs opacity-70">
125
+ <p>// GTA5 HACKING MINIGAME v1.0</p>
126
+ <p>// USE ARROW KEYS TO CONTROL</p>
127
+ </div>
128
+
129
+ <script>
130
+ // Game variables
131
+ const canvas = document.getElementById('gameCanvas');
132
+ const ctx = canvas.getContext('2d');
133
+ const startScreen = document.getElementById('startScreen');
134
+ const gameOverScreen = document.getElementById('gameOverScreen');
135
+ const startBtn = document.getElementById('startBtn');
136
+ const restartBtn = document.getElementById('restartBtn');
137
+ const quitBtn = document.getElementById('quitBtn');
138
+ const scoreDisplay = document.getElementById('scoreDisplay');
139
+ const timeDisplay = document.getElementById('timeDisplay');
140
+ const levelDisplay = document.getElementById('levelDisplay');
141
+ const multiplierDisplay = document.getElementById('multiplierDisplay');
142
+ const finalScore = document.getElementById('finalScore');
143
+ const completionText = document.getElementById('completionText');
144
+ const highScoreDisplay = document.getElementById('highScoreDisplay');
145
+ const lastScoreDisplay = document.getElementById('lastScoreDisplay');
146
+
147
+ // Game state
148
+ let snake = [];
149
+ let food = [];
150
+ let direction = 'right';
151
+ let nextDirection = 'right';
152
+ let gameSpeed = 150;
153
+ let gameLoop;
154
+ let score = 0;
155
+ let level = 1;
156
+ let multiplier = 1;
157
+ let startTime;
158
+ let elapsedTime = 0;
159
+ let timerInterval;
160
+ let highScore = localStorage.getItem('snakeHighScore') || 0;
161
+ let lastScore = localStorage.getItem('snakeLastScore') || 0;
162
+ let keyOutline = [];
163
+ let outlineCompleted = false;
164
+ let outlineProgress = 0;
165
+
166
+ // Possible key shapes (W, A, S, D, Shift, Ctrl, Space, etc.)
167
+ const keyShapes = [
168
+ // W key (simple version)
169
+ [
170
+ {x: 100, y: 100}, {x: 150, y: 50}, {x: 200, y: 100},
171
+ {x: 175, y: 100}, {x: 175, y: 200}, {x: 200, y: 200},
172
+ {x: 150, y: 250}, {x: 100, y: 200}, {x: 125, y: 200},
173
+ {x: 125, y: 100}, {x: 100, y: 100}
174
+ ],
175
+ // A key
176
+ [
177
+ {x: 100, y: 200}, {x: 150, y: 50}, {x: 200, y: 200},
178
+ {x: 175, y: 150}, {x: 125, y: 150}, {x: 100, y: 200}
179
+ ],
180
+ // S key
181
+ [
182
+ {x: 200, y: 50}, {x: 100, y: 50}, {x: 100, y: 125},
183
+ {x: 200, y: 125}, {x: 200, y: 200}, {x: 100, y: 200}
184
+ ],
185
+ // D key
186
+ [
187
+ {x: 100, y: 50}, {x: 150, y: 50}, {x: 175, y: 75},
188
+ {x: 175, y: 175}, {x: 150, y: 200}, {x: 100, y: 200},
189
+ {x: 100, y: 50}
190
+ ],
191
+ // Shift key (simple rectangle)
192
+ [
193
+ {x: 50, y: 225}, {x: 250, y: 225},
194
+ {x: 250, y: 275}, {x: 50, y: 275},
195
+ {x: 50, y: 225}
196
+ ],
197
+ // Space bar
198
+ [
199
+ {x: 50, y: 250}, {x: 250, y: 250},
200
+ {x: 250, y: 275}, {x: 50, y: 275},
201
+ {x: 50, y: 250}
202
+ ]
203
+ ];
204
+
205
+ // Initialize displays
206
+ highScoreDisplay.textContent = highScore;
207
+ lastScoreDisplay.textContent = lastScore;
208
+
209
+ // Start game
210
+ startBtn.addEventListener('click', startGame);
211
+ restartBtn.addEventListener('click', startGame);
212
+ quitBtn.addEventListener('click', () => {
213
+ gameOverScreen.classList.add('hidden');
214
+ startScreen.classList.remove('hidden');
215
+ });
216
+
217
+ function startGame() {
218
+ // Reset game state
219
+ snake = [
220
+ {x: 50, y: 250},
221
+ {x: 40, y: 250},
222
+ {x: 30, y: 250}
223
+ ];
224
+
225
+ direction = 'right';
226
+ nextDirection = 'right';
227
+ score = 0;
228
+ level = 1;
229
+ multiplier = 1;
230
+ elapsedTime = 0;
231
+ outlineCompleted = false;
232
+ outlineProgress = 0;
233
+
234
+ // Generate a random key outline
235
+ const randomShapeIndex = Math.floor(Math.random() * keyShapes.length);
236
+ keyOutline = keyShapes[randomShapeIndex];
237
+
238
+ // Adjust outline coordinates to fit better on canvas
239
+ keyOutline = keyOutline.map(point => ({
240
+ x: point.x + 100,
241
+ y: point.y + 100
242
+ }));
243
+
244
+ // Hide screens
245
+ startScreen.classList.add('hidden');
246
+ gameOverScreen.classList.add('hidden');
247
+
248
+ // Update displays
249
+ scoreDisplay.textContent = score;
250
+ levelDisplay.textContent = level;
251
+ multiplierDisplay.textContent = multiplier + 'x';
252
+
253
+ // Start timer
254
+ startTime = Date.now();
255
+ if (timerInterval) clearInterval(timerInterval);
256
+ timerInterval = setInterval(updateTimer, 1000);
257
+
258
+ // Start game loop
259
+ if (gameLoop) clearInterval(gameLoop);
260
+ gameLoop = setInterval(gameStep, gameSpeed);
261
+
262
+ // Draw initial state
263
+ draw();
264
+ }
265
+
266
+ function updateTimer() {
267
+ elapsedTime = Math.floor((Date.now() - startTime) / 1000);
268
+ const minutes = Math.floor(elapsedTime / 60).toString().padStart(2, '0');
269
+ const seconds = (elapsedTime % 60).toString().padStart(2, '0');
270
+ timeDisplay.textContent = `${minutes}:${seconds}`;
271
+ }
272
+
273
+ function gameStep() {
274
+ // Update direction
275
+ direction = nextDirection;
276
+
277
+ // Move snake
278
+ const head = {...snake[0]};
279
+
280
+ switch(direction) {
281
+ case 'up':
282
+ head.y -= 10;
283
+ break;
284
+ case 'down':
285
+ head.y += 10;
286
+ break;
287
+ case 'left':
288
+ head.x -= 10;
289
+ break;
290
+ case 'right':
291
+ head.x += 10;
292
+ break;
293
+ }
294
+
295
+ // Check for collisions with walls
296
+ if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height) {
297
+ gameOver();
298
+ return;
299
+ }
300
+
301
+ // Check for collisions with self
302
+ for (let i = 0; i < snake.length; i++) {
303
+ if (head.x === snake[i].x && head.y === snake[i].y) {
304
+ gameOver();
305
+ return;
306
+ }
307
+ }
308
+
309
+ // Add new head
310
+ snake.unshift(head);
311
+
312
+ // Check for outline tracing
313
+ checkOutlineTracing(head);
314
+
315
+ // Check if snake should grow (based on outline progress)
316
+ if (outlineProgress % 5 === 0 && outlineProgress > 0 && !outlineCompleted) {
317
+ // Don't remove tail (snake grows)
318
+ multiplier = Math.floor(outlineProgress / 5) + 1;
319
+ multiplierDisplay.textContent = multiplier + 'x';
320
+ } else {
321
+ // Remove tail (snake doesn't grow)
322
+ snake.pop();
323
+ }
324
+
325
+ // Check if outline is completed
326
+ if (outlineProgress >= keyOutline.length - 1 && !outlineCompleted) {
327
+ outlineCompleted = true;
328
+ score += 100 * multiplier * level;
329
+ level++;
330
+ levelDisplay.textContent = level;
331
+
332
+ // Increase speed every 2 levels
333
+ if (level % 2 === 0) {
334
+ gameSpeed = Math.max(50, gameSpeed - 10);
335
+ clearInterval(gameLoop);
336
+ gameLoop = setInterval(gameStep, gameSpeed);
337
+ }
338
+
339
+ // Generate new outline
340
+ const randomShapeIndex = Math.floor(Math.random() * keyShapes.length);
341
+ keyOutline = keyShapes[randomShapeIndex];
342
+
343
+ // Adjust outline coordinates to fit better on canvas
344
+ keyOutline = keyOutline.map(point => ({
345
+ x: point.x + 100,
346
+ y: point.y + 100
347
+ }));
348
+
349
+ outlineProgress = 0;
350
+ outlineCompleted = false;
351
+ }
352
+
353
+ // Update score
354
+ scoreDisplay.textContent = score;
355
+
356
+ // Redraw
357
+ draw();
358
+ }
359
+
360
+ function checkOutlineTracing(head) {
361
+ if (outlineCompleted) return;
362
+
363
+ // Check if head is close to the next point in outline
364
+ const nextPoint = keyOutline[outlineProgress + 1];
365
+ const distance = Math.sqrt(
366
+ Math.pow(head.x - nextPoint.x, 2) +
367
+ Math.pow(head.y - nextPoint.y, 2)
368
+ );
369
+
370
+ if (distance < 15) {
371
+ outlineProgress++;
372
+ score += 5 * multiplier;
373
+
374
+ // Bonus for completing segments
375
+ if (outlineProgress % 5 === 0) {
376
+ score += 20 * multiplier;
377
+ }
378
+ }
379
+ }
380
+
381
+ function draw() {
382
+ // Clear canvas
383
+ ctx.fillStyle = 'rgba(0, 10, 20, 0.7)';
384
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
385
+
386
+ // Draw grid
387
+ drawGrid();
388
+
389
+ // Draw key outline
390
+ drawKeyOutline();
391
+
392
+ // Draw snake
393
+ drawSnake();
394
+
395
+ // Draw progress indicator
396
+ drawProgress();
397
+ }
398
+
399
+ function drawGrid() {
400
+ ctx.strokeStyle = 'rgba(0, 255, 255, 0.1)';
401
+ ctx.lineWidth = 1;
402
+
403
+ // Vertical lines
404
+ for (let x = 0; x < canvas.width; x += 30) {
405
+ ctx.beginPath();
406
+ ctx.moveTo(x, 0);
407
+ ctx.lineTo(x, canvas.height);
408
+ ctx.stroke();
409
+ }
410
+
411
+ // Horizontal lines
412
+ for (let y = 0; y < canvas.height; y += 30) {
413
+ ctx.beginPath();
414
+ ctx.moveTo(0, y);
415
+ ctx.lineTo(canvas.width, y);
416
+ ctx.stroke();
417
+ }
418
+ }
419
+
420
+ function drawKeyOutline() {
421
+ if (keyOutline.length < 2) return;
422
+
423
+ ctx.strokeStyle = 'rgba(255, 0, 255, 0.7)';
424
+ ctx.lineWidth = 3;
425
+ ctx.beginPath();
426
+ ctx.moveTo(keyOutline[0].x, keyOutline[0].y);
427
+
428
+ for (let i = 1; i <= outlineProgress; i++) {
429
+ ctx.lineTo(keyOutline[i].x, keyOutline[i].y);
430
+ }
431
+
432
+ ctx.stroke();
433
+
434
+ // Draw remaining outline in dimmer color
435
+ if (outlineProgress < keyOutline.length - 1) {
436
+ ctx.strokeStyle = 'rgba(255, 0, 255, 0.2)';
437
+ ctx.beginPath();
438
+ ctx.moveTo(keyOutline[outlineProgress].x, keyOutline[outlineProgress].y);
439
+
440
+ for (let i = outlineProgress + 1; i < keyOutline.length; i++) {
441
+ ctx.lineTo(keyOutline[i].x, keyOutline[i].y);
442
+ }
443
+
444
+ ctx.stroke();
445
+ }
446
+
447
+ // Draw points
448
+ ctx.fillStyle = 'magenta';
449
+ for (let i = 0; i < keyOutline.length; i++) {
450
+ ctx.beginPath();
451
+ ctx.arc(keyOutline[i].x, keyOutline[i].y, 3, 0, Math.PI * 2);
452
+ ctx.fill();
453
+ }
454
+ }
455
+
456
+ function drawSnake() {
457
+ // Draw head
458
+ const head = snake[0];
459
+ ctx.fillStyle = 'cyan';
460
+ ctx.beginPath();
461
+ ctx.arc(head.x, head.y, 6, 0, Math.PI * 2);
462
+ ctx.fill();
463
+
464
+ // Add glow effect
465
+ ctx.shadowColor = 'cyan';
466
+ ctx.shadowBlur = 10;
467
+
468
+ // Draw body
469
+ ctx.fillStyle = 'rgba(0, 255, 255, 0.8)';
470
+ for (let i = 1; i < snake.length; i++) {
471
+ ctx.beginPath();
472
+ ctx.arc(snake[i].x, snake[i].y, 4, 0, Math.PI * 2);
473
+ ctx.fill();
474
+ }
475
+
476
+ // Remove glow
477
+ ctx.shadowColor = 'transparent';
478
+ }
479
+
480
+ function drawProgress() {
481
+ const progressPercent = (outlineProgress / (keyOutline.length - 1)) * 100;
482
+
483
+ ctx.fillStyle = 'rgba(0, 255, 255, 0.2)';
484
+ ctx.fillRect(20, 20, 200, 10);
485
+
486
+ ctx.fillStyle = 'cyan';
487
+ ctx.fillRect(20, 20, 200 * (progressPercent / 100), 10);
488
+
489
+ ctx.strokeStyle = 'cyan';
490
+ ctx.strokeRect(20, 20, 200, 10);
491
+
492
+ ctx.fillStyle = 'white';
493
+ ctx.font = '10px Orbitron';
494
+ ctx.fillText(`TRACE PROGRESS: ${Math.round(progressPercent)}%`, 20, 35);
495
+ }
496
+
497
+ function gameOver() {
498
+ clearInterval(gameLoop);
499
+ clearInterval(timerInterval);
500
+
501
+ // Update scores
502
+ lastScore = score;
503
+ if (score > highScore) {
504
+ highScore = score;
505
+ localStorage.setItem('snakeHighScore', highScore);
506
+ }
507
+ localStorage.setItem('snakeLastScore', lastScore);
508
+
509
+ // Update game over screen
510
+ finalScore.textContent = `SCORE: ${score}`;
511
+
512
+ const completionPercent = outlineProgress / (keyOutline.length - 1) * 100;
513
+ if (completionPercent < 30) {
514
+ completionText.textContent = "HACK FAILED - TRACE INCOMPLETE";
515
+ } else if (completionPercent < 70) {
516
+ completionText.textContent = "PARTIAL HACK COMPLETE";
517
+ } else {
518
+ completionText.textContent = "NEARLY COMPLETE - TRY AGAIN";
519
+ }
520
+
521
+ gameOverScreen.classList.remove('hidden');
522
+ }
523
+
524
+ // Handle keyboard input
525
+ document.addEventListener('keydown', (e) => {
526
+ switch(e.key) {
527
+ case 'ArrowUp':
528
+ if (direction !== 'down') nextDirection = 'up';
529
+ break;
530
+ case 'ArrowDown':
531
+ if (direction !== 'up') nextDirection = 'down';
532
+ break;
533
+ case 'ArrowLeft':
534
+ if (direction !== 'right') nextDirection = 'left';
535
+ break;
536
+ case 'ArrowRight':
537
+ if (direction !== 'left') nextDirection = 'right';
538
+ break;
539
+ }
540
+ });
541
+
542
+ // Initial draw
543
+ draw();
544
+ </script>
545
+ <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=Mankeysocks/snker" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
546
+ </html>