snker / index.html
Mankeysocks's picture
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
26c1610 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GTA5 HACKER SNAKE</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
body {
font-family: 'Orbitron', sans-serif;
background-color: #0a0a1a;
overflow: hidden;
user-select: none;
}
#gameCanvas {
border: 2px solid rgba(0, 255, 255, 0.3);
box-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
}
.grid-bg {
position: absolute;
width: 100%;
height: 100%;
background:
linear-gradient(rgba(0, 255, 255, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 255, 255, 0.1) 1px, transparent 1px);
background-size: 30px 30px;
z-index: -1;
}
.glow-text {
text-shadow: 0 0 10px cyan, 0 0 20px cyan;
}
.glow-box {
box-shadow: 0 0 15px cyan, inset 0 0 10px cyan;
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 0.7; }
50% { opacity: 1; }
100% { opacity: 0.7; }
}
#keyOutline {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 5s linear forwards;
}
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
</style>
</head>
<body class="text-cyan-400 h-screen flex flex-col items-center justify-center relative">
<div class="grid-bg"></div>
<div class="absolute top-4 left-4 flex items-center gap-2">
<div class="w-3 h-3 rounded-full bg-red-500 animate-pulse"></div>
<span class="text-xs">LIVE FEED</span>
</div>
<div class="absolute top-4 right-4 text-xs">
<div class="flex gap-4">
<span>CONNECTION: <span class="text-green-500">SECURE</span></span>
<span>USER: <span class="text-cyan-300">PLAYER_1</span></span>
</div>
</div>
<h1 class="text-4xl font-bold mb-2 glow-text">// HACKER_SNAKE.EXE</h1>
<p class="text-xs mb-6 pulse">TRACE THE KEY PATTERN WITHOUT COLLISION</p>
<div class="relative">
<canvas id="gameCanvas" width="500" height="500" class="bg-black"></canvas>
<div id="startScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-80">
<h2 class="text-2xl mb-4 glow-text">GTA5 HACKING TERMINAL</h2>
<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>
<button id="startBtn" class="px-6 py-2 bg-cyan-900 hover:bg-cyan-700 glow-box rounded-md font-bold transition-all">
INITIATE HACK
</button>
<div class="mt-6 text-xs">
<p>HIGH SCORE: <span id="highScoreDisplay">0</span></p>
<p>LAST SCORE: <span id="lastScoreDisplay">0</span></p>
</div>
</div>
<div id="gameOverScreen" class="absolute inset-0 hidden flex-col items-center justify-center bg-black bg-opacity-80">
<h2 class="text-2xl mb-2 glow-text">HACK TERMINATED</h2>
<p class="text-xl mb-2" id="finalScore">SCORE: 0</p>
<p class="text-sm mb-6" id="completionText">PARTIAL HACK COMPLETE</p>
<div class="flex gap-4">
<button id="restartBtn" class="px-4 py-2 bg-cyan-900 hover:bg-cyan-700 glow-box rounded-md font-bold transition-all">
RETRY
</button>
<button id="quitBtn" class="px-4 py-2 bg-purple-900 hover:bg-purple-700 glow-box rounded-md font-bold transition-all">
EXIT
</button>
</div>
</div>
</div>
<div class="mt-4 flex gap-8 text-sm">
<div>
<p>SCORE: <span id="scoreDisplay">0</span></p>
<p>TIME: <span id="timeDisplay">00:00</span></p>
</div>
<div>
<p>LEVEL: <span id="levelDisplay">1</span></p>
<p>MULTIPLIER: <span id="multiplierDisplay">1x</span></p>
</div>
</div>
<div class="absolute bottom-4 left-4 text-xs opacity-70">
<p>// GTA5 HACKING MINIGAME v1.0</p>
<p>// USE ARROW KEYS TO CONTROL</p>
</div>
<script>
// Game variables
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startScreen = document.getElementById('startScreen');
const gameOverScreen = document.getElementById('gameOverScreen');
const startBtn = document.getElementById('startBtn');
const restartBtn = document.getElementById('restartBtn');
const quitBtn = document.getElementById('quitBtn');
const scoreDisplay = document.getElementById('scoreDisplay');
const timeDisplay = document.getElementById('timeDisplay');
const levelDisplay = document.getElementById('levelDisplay');
const multiplierDisplay = document.getElementById('multiplierDisplay');
const finalScore = document.getElementById('finalScore');
const completionText = document.getElementById('completionText');
const highScoreDisplay = document.getElementById('highScoreDisplay');
const lastScoreDisplay = document.getElementById('lastScoreDisplay');
// Game state
let snake = [];
let food = [];
let direction = 'right';
let nextDirection = 'right';
let gameSpeed = 150;
let gameLoop;
let score = 0;
let level = 1;
let multiplier = 1;
let startTime;
let elapsedTime = 0;
let timerInterval;
let highScore = localStorage.getItem('snakeHighScore') || 0;
let lastScore = localStorage.getItem('snakeLastScore') || 0;
let keyOutline = [];
let outlineCompleted = false;
let outlineProgress = 0;
// Possible key shapes (W, A, S, D, Shift, Ctrl, Space, etc.)
const keyShapes = [
// W key (simple version)
[
{x: 100, y: 100}, {x: 150, y: 50}, {x: 200, y: 100},
{x: 175, y: 100}, {x: 175, y: 200}, {x: 200, y: 200},
{x: 150, y: 250}, {x: 100, y: 200}, {x: 125, y: 200},
{x: 125, y: 100}, {x: 100, y: 100}
],
// A key
[
{x: 100, y: 200}, {x: 150, y: 50}, {x: 200, y: 200},
{x: 175, y: 150}, {x: 125, y: 150}, {x: 100, y: 200}
],
// S key
[
{x: 200, y: 50}, {x: 100, y: 50}, {x: 100, y: 125},
{x: 200, y: 125}, {x: 200, y: 200}, {x: 100, y: 200}
],
// D key
[
{x: 100, y: 50}, {x: 150, y: 50}, {x: 175, y: 75},
{x: 175, y: 175}, {x: 150, y: 200}, {x: 100, y: 200},
{x: 100, y: 50}
],
// Shift key (simple rectangle)
[
{x: 50, y: 225}, {x: 250, y: 225},
{x: 250, y: 275}, {x: 50, y: 275},
{x: 50, y: 225}
],
// Space bar
[
{x: 50, y: 250}, {x: 250, y: 250},
{x: 250, y: 275}, {x: 50, y: 275},
{x: 50, y: 250}
]
];
// Initialize displays
highScoreDisplay.textContent = highScore;
lastScoreDisplay.textContent = lastScore;
// Start game
startBtn.addEventListener('click', startGame);
restartBtn.addEventListener('click', startGame);
quitBtn.addEventListener('click', () => {
gameOverScreen.classList.add('hidden');
startScreen.classList.remove('hidden');
});
function startGame() {
// Reset game state
snake = [
{x: 50, y: 250},
{x: 40, y: 250},
{x: 30, y: 250}
];
direction = 'right';
nextDirection = 'right';
score = 0;
level = 1;
multiplier = 1;
elapsedTime = 0;
outlineCompleted = false;
outlineProgress = 0;
// Generate a random key outline
const randomShapeIndex = Math.floor(Math.random() * keyShapes.length);
keyOutline = keyShapes[randomShapeIndex];
// Adjust outline coordinates to fit better on canvas
keyOutline = keyOutline.map(point => ({
x: point.x + 100,
y: point.y + 100
}));
// Hide screens
startScreen.classList.add('hidden');
gameOverScreen.classList.add('hidden');
// Update displays
scoreDisplay.textContent = score;
levelDisplay.textContent = level;
multiplierDisplay.textContent = multiplier + 'x';
// Start timer
startTime = Date.now();
if (timerInterval) clearInterval(timerInterval);
timerInterval = setInterval(updateTimer, 1000);
// Start game loop
if (gameLoop) clearInterval(gameLoop);
gameLoop = setInterval(gameStep, gameSpeed);
// Draw initial state
draw();
}
function updateTimer() {
elapsedTime = Math.floor((Date.now() - startTime) / 1000);
const minutes = Math.floor(elapsedTime / 60).toString().padStart(2, '0');
const seconds = (elapsedTime % 60).toString().padStart(2, '0');
timeDisplay.textContent = `${minutes}:${seconds}`;
}
function gameStep() {
// Update direction
direction = nextDirection;
// Move snake
const head = {...snake[0]};
switch(direction) {
case 'up':
head.y -= 10;
break;
case 'down':
head.y += 10;
break;
case 'left':
head.x -= 10;
break;
case 'right':
head.x += 10;
break;
}
// Check for collisions with walls
if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height) {
gameOver();
return;
}
// Check for collisions with self
for (let i = 0; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
gameOver();
return;
}
}
// Add new head
snake.unshift(head);
// Check for outline tracing
checkOutlineTracing(head);
// Check if snake should grow (based on outline progress)
if (outlineProgress % 5 === 0 && outlineProgress > 0 && !outlineCompleted) {
// Don't remove tail (snake grows)
multiplier = Math.floor(outlineProgress / 5) + 1;
multiplierDisplay.textContent = multiplier + 'x';
} else {
// Remove tail (snake doesn't grow)
snake.pop();
}
// Check if outline is completed
if (outlineProgress >= keyOutline.length - 1 && !outlineCompleted) {
outlineCompleted = true;
score += 100 * multiplier * level;
level++;
levelDisplay.textContent = level;
// Increase speed every 2 levels
if (level % 2 === 0) {
gameSpeed = Math.max(50, gameSpeed - 10);
clearInterval(gameLoop);
gameLoop = setInterval(gameStep, gameSpeed);
}
// Generate new outline
const randomShapeIndex = Math.floor(Math.random() * keyShapes.length);
keyOutline = keyShapes[randomShapeIndex];
// Adjust outline coordinates to fit better on canvas
keyOutline = keyOutline.map(point => ({
x: point.x + 100,
y: point.y + 100
}));
outlineProgress = 0;
outlineCompleted = false;
}
// Update score
scoreDisplay.textContent = score;
// Redraw
draw();
}
function checkOutlineTracing(head) {
if (outlineCompleted) return;
// Check if head is close to the next point in outline
const nextPoint = keyOutline[outlineProgress + 1];
const distance = Math.sqrt(
Math.pow(head.x - nextPoint.x, 2) +
Math.pow(head.y - nextPoint.y, 2)
);
if (distance < 15) {
outlineProgress++;
score += 5 * multiplier;
// Bonus for completing segments
if (outlineProgress % 5 === 0) {
score += 20 * multiplier;
}
}
}
function draw() {
// Clear canvas
ctx.fillStyle = 'rgba(0, 10, 20, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw grid
drawGrid();
// Draw key outline
drawKeyOutline();
// Draw snake
drawSnake();
// Draw progress indicator
drawProgress();
}
function drawGrid() {
ctx.strokeStyle = 'rgba(0, 255, 255, 0.1)';
ctx.lineWidth = 1;
// Vertical lines
for (let x = 0; x < canvas.width; x += 30) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
// Horizontal lines
for (let y = 0; y < canvas.height; y += 30) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
}
function drawKeyOutline() {
if (keyOutline.length < 2) return;
ctx.strokeStyle = 'rgba(255, 0, 255, 0.7)';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(keyOutline[0].x, keyOutline[0].y);
for (let i = 1; i <= outlineProgress; i++) {
ctx.lineTo(keyOutline[i].x, keyOutline[i].y);
}
ctx.stroke();
// Draw remaining outline in dimmer color
if (outlineProgress < keyOutline.length - 1) {
ctx.strokeStyle = 'rgba(255, 0, 255, 0.2)';
ctx.beginPath();
ctx.moveTo(keyOutline[outlineProgress].x, keyOutline[outlineProgress].y);
for (let i = outlineProgress + 1; i < keyOutline.length; i++) {
ctx.lineTo(keyOutline[i].x, keyOutline[i].y);
}
ctx.stroke();
}
// Draw points
ctx.fillStyle = 'magenta';
for (let i = 0; i < keyOutline.length; i++) {
ctx.beginPath();
ctx.arc(keyOutline[i].x, keyOutline[i].y, 3, 0, Math.PI * 2);
ctx.fill();
}
}
function drawSnake() {
// Draw head
const head = snake[0];
ctx.fillStyle = 'cyan';
ctx.beginPath();
ctx.arc(head.x, head.y, 6, 0, Math.PI * 2);
ctx.fill();
// Add glow effect
ctx.shadowColor = 'cyan';
ctx.shadowBlur = 10;
// Draw body
ctx.fillStyle = 'rgba(0, 255, 255, 0.8)';
for (let i = 1; i < snake.length; i++) {
ctx.beginPath();
ctx.arc(snake[i].x, snake[i].y, 4, 0, Math.PI * 2);
ctx.fill();
}
// Remove glow
ctx.shadowColor = 'transparent';
}
function drawProgress() {
const progressPercent = (outlineProgress / (keyOutline.length - 1)) * 100;
ctx.fillStyle = 'rgba(0, 255, 255, 0.2)';
ctx.fillRect(20, 20, 200, 10);
ctx.fillStyle = 'cyan';
ctx.fillRect(20, 20, 200 * (progressPercent / 100), 10);
ctx.strokeStyle = 'cyan';
ctx.strokeRect(20, 20, 200, 10);
ctx.fillStyle = 'white';
ctx.font = '10px Orbitron';
ctx.fillText(`TRACE PROGRESS: ${Math.round(progressPercent)}%`, 20, 35);
}
function gameOver() {
clearInterval(gameLoop);
clearInterval(timerInterval);
// Update scores
lastScore = score;
if (score > highScore) {
highScore = score;
localStorage.setItem('snakeHighScore', highScore);
}
localStorage.setItem('snakeLastScore', lastScore);
// Update game over screen
finalScore.textContent = `SCORE: ${score}`;
const completionPercent = outlineProgress / (keyOutline.length - 1) * 100;
if (completionPercent < 30) {
completionText.textContent = "HACK FAILED - TRACE INCOMPLETE";
} else if (completionPercent < 70) {
completionText.textContent = "PARTIAL HACK COMPLETE";
} else {
completionText.textContent = "NEARLY COMPLETE - TRY AGAIN";
}
gameOverScreen.classList.remove('hidden');
}
// Handle keyboard input
document.addEventListener('keydown', (e) => {
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;
}
});
// 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=Mankeysocks/snker" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>