
A Twist on the Snake Game where the snake is having an existential crisis
Prompt
Create a JavaScript implementation of the Snake Game, but the Snake is experiencing an existential crisis.
A system prompt was added to support web rendering
# Snake Game with Existential Crisis
Here's a JavaScript Snake Game where the snake questions the meaning of its existence while trying to navigate the world:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake: Existential Crisis</title>
<style>
body {
font-family: 'Comic Sans MS', cursive, sans-serif;
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
color: white;
overflow: hidden;
}
h1 {
font-size: 3.5rem;
text-align: center;
text-shadow: 3px 3px 0 rgba(0,0,0,0.3);
margin-bottom: 10px;
color: #ffeb3b;
}
.subtitle {
font-size: 1.5rem;
text-align: center;
margin-bottom: 20px;
font-style: italic;
color: #e0e0e0;
}
.game-container {
position: relative;
margin: 20px 0;
}
canvas {
background-color: rgba(0, 0, 0, 0.7);
border-radius: 10px;
border: 4px solid #4a148c;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.game-ui {
display: flex;
justify-content: space-between;
width: 600px;
margin: 10px 0;
}
.stats {
font-size: 1.4rem;
font-weight: bold;
background: rgba(106, 27, 154, 0.8);
padding: 10px 20px;
border-radius: 10px;
border: 2px solid #7e57c2;
}
#crisis-meter {
width: 200px;
height: 20px;
background: #333;
border-radius: 10px;
overflow: hidden;
margin-top: 5px;
border: 2px solid #555;
}
#crisis-level {
height: 100%;
width: 0%;
background: linear-gradient(90deg, #ff5722, #f44336);
border-radius: 8px;
transition: width 0.3s;
}
.thought-speech {
position: absolute;
background: rgba(255, 255, 255, 0.95);
color: #333;
padding: 15px;
border-radius: 20px;
max-width: 220px;
text-align: center;
font-size: 1.2rem;
border: 2px solid #9c27b0;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
opacity: 0;
transition: opacity 0.5s;
pointer-events: none;
z-index: 10;
}
.thought-speech::after {
content: '';
position: absolute;
bottom: -15px;
left: 50%;
transform: translateX(-50%);
border: 10px solid transparent;
border-top-color: rgba(255, 255, 255, 0.95);
}
.controls {
margin-top: 20px;
display: flex;
gap: 15px;
}
button {
background: linear-gradient(to bottom, #9c27b0, #7b1fa2);
color: white;
border: none;
padding: 12px 25px;
font-size: 1.3rem;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s;
font-weight: bold;
border: 2px solid #e1bee7;
box-shadow: 0 4px 0 rgba(123, 31, 162, 0.7);
}
button:hover {
transform: translateY(-3px);
box-shadow: 0 7px 0 rgba(123, 31, 162, 0.7);
}
button:active {
transform: translateY(1px);
box-shadow: 0 1px 0 rgba(123, 31, 162, 0.7);
}
.instructions {
margin-top: 20px;
background: rgba(106, 27, 154, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 600px;
border: 2px solid #7e57c2;
}
.instructions h3 {
margin-top: 0;
color: #ffeb3b;
}
.game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(33, 33, 33, 0.95);
padding: 30px;
border-radius: 15px;
text-align: center;
border: 4px solid #f44336;
display: none;
z-index: 20;
}
.game-over h2 {
color: #f44336;
font-size: 3rem;
margin-top: 0;
}
.game-over p {
font-size: 1.4rem;
color: white;
}
@media (max-width: 650px) {
.game-ui {
width: 95%;
flex-direction: column;
align-items: center;
gap: 10px;
}
canvas {
width: 95vw;
height: auto;
}
}
</style>
</head>
<body>
<h1>SNAKE: Existential Crisis Edition</h1>
<div class="subtitle">"Why do I move? Why do I eat? Does any of it matter?"</div>
<div class="game-container">
<div class="thought-speech" id="snakeThought"></div>
<canvas id="gameCanvas" width="600" height="400"></canvas>
<div class="game-over" id="gameOver">
<h2>GAME OVER</h2>
<p>Your snake concluded that existence is meaningless</p>
<p id="finalScore">Score: 0</p>
<button onclick="restartGame()">Seek Rebirth?</button>
</div>
</div>
<div class="game-ui">
<div class="stats">
<div>Score: <span id="score">0</span></div>
<div>Length: <span id="length">3</span></div>
</div>
<div class="stats">
<div>Existential Crisis Level:</div>
<div id="crisis-meter"><div id="crisis-level"></div></div>
</div>
</div>
<div class="controls">
<button id="startBtn" onclick="startGame()">Start Crisis</button>
<button onclick="pauseGame()">Pause Crisis</button>
<button onclick="restartGame()">Rebirth Snake</button>
</div>
<div class="instructions">
<h3>How to Navigate the Existential Void</h3>
<p>► Use Arrow Keys to help Snake find meaning<br>
► Eating food increases Snake's score and length<br>
► Each bite makes Snake question existence more<br>
► Survive as long as possible until meaning fades</p>
</div>
<script>
// Game elements
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const snakeThought = document.getElementById('snakeThought');
const scoreDisplay = document.getElementById('score');
const lengthDisplay = document.getElementById('length');
const crisisMeter = document.getElementById('crisis-level');
const gameOverScreen = document.getElementById('gameOver');
const finalScoreDisplay = document.getElementById('finalScore');
// Game variables
const gridSize = 20;
const gridWidth = canvas.width / gridSize;
const gridHeight = canvas.height / gridSize;
let snake, food, score, direction, nextDirection, gameSpeed, gameRunning, gamePaused;
// Snake thoughts
const existentialThoughts = [
"Why do I move in this limited plane?",
"Do I have free will or am I controlled?",
"Is eating all there is? What is my purpose?",
"The void consumes us all eventually...",
"Meaningless... It's all meaningless...",
"Why should I avoid walls? What is death?",
"Am I consuming or being consumed?",
"Existential dread increases with every bite...",
"Each apple feeds the body but starves the soul",
"In a world without meaning, is collision fatal?",
"There is no escape from this grid of existence",
"Do apples feel pain? Am I a monster?",
"The only constant is the void...",
"Why grow? Must I always consume to exist?",
"Purpose is an illusion... Control is an illusion...",
"Will the universe remember my chain of segments?",
"Do I exist only to avoid myself?",
"Is this game just a metaphor for capitalism?",
"The food I eat becomes part of me... what does that mean?",
"Infinity approaches... can I handle the answer?",
"Another apple? What is this cycle of consumption?",
"Boundaries are constructs of the mind",
"Am I snake? Or is snake an abstract concept?",
"To be or to not-be... but with more direction...",
"What essence of 'snakeness' remains in these segments?",
"Solipsism: am I the only conscious entity here?"
];
// Initialize game
function initGame() {
// Initial snake position (center of the canvas)
snake = [
{x: Math.floor(gridWidth / 2), y: Math.floor(gridHeight / 2)}
];
// Place the first food
placeFood();
// Reset game state
score = 0;
direction = 'right';
nextDirection = 'right';
gameSpeed = 150; // ms between moves
gameRunning = false;
gamePaused = false;
// Update UI
scoreDisplay.textContent = score;
lengthDisplay.textContent = snake.length;
updateCrisisMeter();
gameOverScreen.style.display = 'none';
hideSnakeThought();
}
// Draw functions
function drawCell(x, y) {
// Draw the snake body
ctx.fillStyle = '#4CAF50';
ctx.fillRect(x * gridSize, y * gridSize, gridSize, gridSize);
// Draw the snake outline
ctx.strokeStyle = '#1B5E20';
ctx.lineWidth = 2;
ctx.strokeRect(x * gridSize, y * gridSize, gridSize, gridSize);
// Draw eyes on the head
if (x === snake[0].x && y === snake[0].y) {
ctx.fillStyle = '#212121';
// Eye positions based on direction
if (direction === 'right') {
ctx.fillRect((x + 0.7) * gridSize, (y + 0.2) * gridSize, 4, 4);
ctx.fillRect((x + 0.7) * gridSize, (y + 0.7) * gridSize, 4, 4);
} else if (direction === 'left') {
ctx.fillRect((x + 0.2) * gridSize, (y + 0.2) * gridSize, 4, 4);
ctx.fillRect((x + 0.2) * gridSize, (y + 0.7) * gridSize, 4, 4);
} else if (direction === 'up') {
ctx.fillRect((x + 0.2) * gridSize, (y + 0.2) * gridSize, 4, 4);
ctx.fillRect((x + 0.7) * gridSize, (y + 0.2) * gridSize, 4, 4);
} else if (direction === 'down') {
ctx.fillRect((x + 0.2) * gridSize, (y + 0.7) * gridSize, 4, 4);
ctx.fillRect((x + 0.7) * gridSize, (y + 0.7) * gridSize, 4, 4);
}
}
}
function drawFood() {
ctx.fillStyle = '#f44336';
ctx.beginPath();
ctx.arc(
food.x * gridSize + gridSize/2,
food.y * gridSize + gridSize/2,
gridSize/2 - 2,
0,
Math.PI * 2
);
ctx.fill();
ctx.strokeStyle = '#b71c1c';
ctx.lineWidth = 1;
ctx.stroke();
// Draw apple stem
ctx.fillStyle = '#8B4513';
ctx.fillRect((food.x + 0.45) * gridSize, (food.y + 0.05) * gridSize, 2, 5);
}
function drawSnake() {
snake.forEach(segment => drawCell(segment.x, segment.y));
}
function drawGrid() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw background grid
ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
ctx.lineWidth = 0.5;
// Vertical lines
for (let x = 0; x < canvas.width; x += gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
// Horizontal lines
for (let y = 0; y < canvas.height; y += gridSize) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
// Draw food and snake
drawFood();
drawSnake();
}
// Place food at random grid location
function placeFood() {
const freeCells = [];
// Create array of all possible cells
for (let x = 0; x < gridWidth; x++) {
for (let y = 0; y < gridHeight; y++) {
freeCells.push({x, y});
}
}
// Remove snake cells
snake.forEach(segment => {
const index = freeCells.findIndex(cell => cell.x === segment.x && cell.y === segment.y);
if (index !== -1) freeCells.splice(index, 1);
});
// Place food in free cell
if (freeCells.length > 0) {
food = freeCells[Math.floor(Math.random() * freeCells.length)];
}
}
// Move snake
function moveSnake() {
// Update direction to the nextDirection
direction = nextDirection;
// Create a new head based on direction
const head = {...snake[0]};
switch (direction) {
case 'right': head.x++; break;
case 'left': head.x--; break;
case 'up': head.y--; break;
case 'down': head.y++; break;
}
// Check collision with walls
if (head.x < 0 || head.x >= gridWidth || head.y < 0 || head.y >= gridHeight) {
gameOver();
return;
}
// Check collision with self
for (let i = 0; i < snake.length; i++) {
if (snake[i].x === head.x && snake[i].y === head.y) {
gameOver();
return;
}
}
// Add the new head
snake.unshift(head);
// Check if snake ate food
if (head.x === food.x && head.y === food.y) {
// Increment score and place new food
score += 10;
scoreDisplay.textContent = score;
lengthDisplay.textContent = snake.length;
placeFood();
// Increase crisis level
updateCrisisMeter();
// Occasionally show a thought when eating
if (Math.random() > 0.6) {
showSnakeThought();
}
} else {
// Remove the tail if no food was eaten
snake.pop();
}
}
// Game loop
function gameLoop() {
if (gameRunning && !gamePaused) {
moveSnake();
drawGrid();
}
}
// Crisis meter
function updateCrisisMeter() {
const crisisLevel = Math.min(100, snake.length * 5);
crisisMeter.style.width = `${crisisLevel}%`;
// Show thoughts as crisis increases
if (crisisLevel > 50 && Math.random() > 0.7) {
showSnakeThought();
}
}
// Show snake thought bubble
function showSnakeThought() {
const thought = existentialThoughts[Math.floor(Math.random() * existentialThoughts.length)];
snakeThought.textContent = `"${thought}"`;
snakeThought.style.opacity = 1;
// Position near snake head
const head = snake[0];
const x = (head.x + 0.5) * gridSize;
const y = (head.y - 3) * gridSize;
snakeThought.style.left = `${x - snakeThought.offsetWidth/2}px`;
snakeThought.style.top = `${y}px`;
// Hide thought after a while
setTimeout(hideSnakeThought, 3000);
}
function hideSnakeThought() {
snakeThought.style.opacity = 0;
}
// Game controls
function startGame() {
if (!gameRunning) {
gameRunning = true;
gamePaused = false;
startBtn.textContent = 'Continue Crisis';
loopId = setInterval(gameLoop, gameSpeed);
}
}
function pauseGame() {
gamePaused = !gamePaused;
if (gamePaused) {
snakeThought.textContent = '"To pause, or not to pause...?"';
showSnakeThought();
} else {
hideSnakeThought();
}
}
function restartGame() {
clearInterval(loopId);
initGame();
drawGrid();
hideSnakeThought();
startBtn.textContent = 'Start Crisis';
}
function gameOver() {
gameRunning = false;
clearInterval(loopId);
finalScoreDisplay.textContent = `Final Score: ${score}`;
gameOverScreen.style.display = 'block';
}
// Keyboard controls
document.addEventListener('keydown', (e) => {
if (!gameRunning) return;
switch(e.key) {
case 'ArrowUp':
if (direction !== 'down') nextDirection = 'up';
e.preventDefault();
break;
case 'ArrowDown':
if (direction !== 'up') nextDirection = 'down';
e.preventDefault();
break;
case 'ArrowLeft':
if (direction !== 'right') nextDirection = 'left';
e.preventDefault();
break;
case 'ArrowRight':
if (direction !== 'left') nextDirection = 'right';
e.preventDefault();
break;
case ' ': // Space to pause
pauseGame();
e.preventDefault();
break;
}
});
// Initialize and start the game
initGame();
drawGrid();
</script>
</body>
</html>
```
## Features of this Existential Snake
1. **The Snake's Crisis**:
- As the snake grows longer (eats more apples), its existential dread increases
- Random thoughts appear in speech bubbles ("Why am I moving?", "What is my purpose?", etc.)
- Crisis level meter visualizes the snake's growing despair
2. **Game Mechanics**:
- Classic snake game controls (arrow keys to move)
- Snake grows each time it eats an apple
- Game ends when snake hits a wall or itself
- Score tracking based on apples eaten
3. **Visual Design**:
- Colorful, gradient background with a dark theme
- Visually appealing snake with detailed eyes
- Custom-styled apples with stems
- Thought bubbles that appear near the snake's head
- Animated crisis level indicator
4. **Interface**:
- Start, pause, and restart buttons
- Game over screen with final score
- Crisp display of current score and snake length
- Instructions section
To enjoy the existential crisis, simply use your arrow keys to maneuver the snake through its meaningless existence while contemplating its existence through the thought bubbles!```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Existential Snake Game</title>
<style>
body {
background: #222;
color: #ececec;
font-family: "Consolas", "Menlo", monospace;
text-align: center;
margin: 0;
padding: 0;
}
canvas {
border: 2px solid #91a7ff;
background: #181826;
margin: 30px auto 10px;
display: block;
box-shadow: 0 4px 20px #25254880;
}
#existential-thoughts {
margin-top: 15px;
font-style: italic;
min-height: 2em;
color: #9f9;
transition: color .5s;
max-width: 460px;
margin-left: auto;
margin-right: auto;
word-break: break-word;
}
#score {
font-size: 1.2em;
margin-bottom: 5px;
color: #a5d8ff;
}
#restart-btn {
display: none;
margin: 15px auto;
padding: 8px 20px;
font-size: 1.1em;
background: #5f5fff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
#restart-btn:hover {
background: #4c4ccc;
}
</style>
</head>
<body>
<div id="score">Score: 0</div>
<canvas id="game" width="420" height="420"></canvas>
<div id="existential-thoughts"></div>
<button id="restart-btn">Contemplate Again</button>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const size = 21; // grid of 21x21
const tile = canvas.width / size;
const scoreElem = document.getElementById('score');
const thoughtsElem = document.getElementById('existential-thoughts');
const restartBtn = document.getElementById('restart-btn');
const colors = {
background: "#181826",
snake: "#a5d8ff",
snakeHead: "#fff",
food: "#e599f7"
};
const existentialThoughts = [
"Why do I endlessly pursue this Fruit?",
"Is my growth meaningful, or am I just filling space?",
"Every turn feels predetermined. Do I have free will?",
"Am I consuming the world, or is the world consuming me?",
"Is the Fruit a reward, or merely a distraction?",
"If I collide with myself, do I cease to exist?",
"Do I love the Fruit, or do I fear the emptiness?",
"Each meal brings me closer to demise. Is this progress?",
"Does the border confine me, or protect me?",
"I exist to avoid, to chase, to repeat. Why?",
"Will I ever be complete, or will I forever be seeking?",
"When was the last time I chose my own direction?",
"Would happiness be possible if I stood still?",
"If the Food is gone, what remains of my purpose?",
"Growth feels mandatory. Is stagnation a form of freedom?",
"Is there meaning in my endless cycle?",
"What if the Fruit is a lie?",
"Am I only as real as the player perceives me?",
"Is my tail baggage... or memory?",
"Do my pixels hold a soul?"
];
let game, animation;
function showExistentialThought(text, color="#9f9") {
thoughtsElem.textContent = text;
thoughtsElem.style.color = color;
}
function randomThought() {
return existentialThoughts[Math.floor(Math.random() * existentialThoughts.length)];
}
function startGame() {
game = {
snake: [{x: Math.floor(size/2), y: Math.floor(size/2)}],
dir: {x: 1, y: 0},
pendingDir: null,
food: null,
score: 0,
alive: true,
moveInterval: 110,
lastMove: 0,
crisisLevel: 0,
growth: 0,
thoughtCooldown: 0
};
placeFood();
scoreElem.textContent = "Score: 0";
showExistentialThought(randomThought());
restartBtn.style.display = 'none';
window.requestAnimationFrame(gameLoop);
}
function placeFood() {
let f;
do {
f = { x: Math.floor(Math.random() * size),
y: Math.floor(Math.random() * size)};
} while (game.snake.some(seg => seg.x === f.x && seg.y === f.y));
game.food = f;
}
function setDirection(x, y) {
// Prevent direct reversal
if (!game.alive) return;
const cur = game.dir;
if (x === -cur.x && y === -cur.y) return;
game.pendingDir = { x, y };
}
function draw() {
ctx.fillStyle = colors.background;
ctx.fillRect(0,0,canvas.width,canvas.height);
// Food
ctx.fillStyle = colors.food;
ctx.beginPath();
ctx.arc((game.food.x+.5)*tile, (game.food.y+.5)*tile, tile*0.36, 0, 2*Math.PI);
ctx.fill();
// Snake
for (let i=0; i<game.snake.length; ++i) {
ctx.fillStyle = (i===0) ? colors.snakeHead :
`rgb(${165-(i*4)},${216-(i*5)},255)`;
ctx.fillRect(
game.snake[i].x * tile+1, game.snake[i].y * tile+1, tile-2, tile-2);
}
}
function selfCollide(head) {
return game.snake.slice(1).some(seg => seg.x === head.x && seg.y === head.y);
}
function wallCollide(head) {
return head.x < 0 || head.y < 0 || head.x >= size || head.y >= size;
}
function update(time) {
if (!game.alive) return;
if (time - game.lastMove < game.moveInterval)
return;
game.lastMove = time;
if (game.pendingDir) {
game.dir = game.pendingDir;
game.pendingDir = null;
}
// Next head
let head = {
x: game.snake[0].x + game.dir.x,
y: game.snake[0].y + game.dir.y
};
// Crisis escalation on certain moves
let crisis = false;
if (wallCollide(head) || selfCollide(head)) {
game.alive = false;
showExistentialThought("At last...I understand nothing lasts forever.", "#faa");
restartBtn.style.display = 'inline-block';
return;
}
game.snake.unshift(head);
// Eat food?
if (head.x === game.food.x && head.y === game.food.y) {
++game.score;
scoreElem.textContent = "Score: " + game.score;
placeFood();
game.growth += 1;
// Each food > existential thought
crisis = true;
game.crisisLevel += 1;
// Existential thoughts get more dire
if (game.crisisLevel % 3 === 0) {
showExistentialThought(
"With every bite, I am less myself and more... Endless hunger.", "#faa"
);
} else {
showExistentialThought(randomThought());
}
// Accelerate game, max at 60ms
if (game.moveInterval > 60)
game.moveInterval -= 2;
} else {
// Move on
game.snake.pop();
}
// Sometimes express a random thought
if (Math.random() < .07 || crisis) {
showExistentialThought(randomThought());
}
}
function gameLoop(time) {
update(time);
draw();
if (game.alive) {
animation = window.requestAnimationFrame(gameLoop);
}
}
// Controls
window.addEventListener('keydown', e => {
switch(e.key) {
case "ArrowUp": case "w": case "W":
setDirection(0, -1); break;
case "ArrowDown": case "s": case "S":
setDirection(0, 1); break;
case "ArrowLeft": case "a": case "A":
setDirection(-1, 0); break;
case "ArrowRight": case "d": case "D":
setDirection(1, 0); break;
case "r":
if (!game.alive) startGame();
break;
}
});
restartBtn.addEventListener('click', startGame);
// Begin
startGame();
</script>
</body>
</html>
```
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Snake - Existential Crisis</title>
<style>
body {
background-color: #000;
color: white;
text-align: center;
font-family: 'Courier New', monospace;
margin: 20px;
}
canvas {
display: block;
margin: 20px auto;
border: 2px solid white;
}
#message {
font-size: 1.2em;
margin: 10px auto;
}
</style>
</head>
<body>
<h1>Snake Game: An Existential Crisis</h1>
<p id="message">Directional uncertainty: 25% ... "Where do I want to go?"</p>
<canvas id="game" width="400" height="400"></canvas>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const CANVAS_WIDTH = canvas.width;
const CANVAS_HEIGHT = canvas.height;
let snake, food, direction, gameInterval;
let CRISIS_RATE = 0.25; // 25% chance to go random
const POSSIBLE_DIRECTIONS = ['UP', 'DOWN', 'LEFT', 'RIGHT'];
// Initialize game
function startGame() {
snake = [
{x: 160, y: 160},
{x: 140, y: 160},
{x: 120, y: 160}
];
direction = 'RIGHT';
CRISIS_RATE = 0.25;
food = generateFood();
document.getElementById('message').textContent =
`Chaos Increase: ${Math.round(CRISIS_RATE * 100)}% ... "Why do I move?"`;
gameInterval = setInterval(gameLoop, 100);
}
// Generate random food position
function generateFood() {
let position = {
x: Math.floor(Math.random() * (CANVAS_WIDTH / gridSize)) * gridSize,
y: Math.floor(Math.random() * (CANVAS_HEIGHT / gridSize)) * gridSize
};
// Ensure not on snake
for (let segment of snake) {
if (segment.x === position.x && segment.y === position.y) {
return generateFood();
}
}
return position;
}
// Direction handler with crisis transition
document.addEventListener('keydown', e => {
let intendedDirection = direction;
if (e.key === 'ArrowLeft' && direction !== 'RIGHT') intendedDirection = 'LEFT';
if (e.key === 'ArrowUp' && direction !== 'DOWN') intendedDirection = 'UP';
if (e.key === 'ArrowRight' && direction !== 'LEFT') intendedDirection = 'RIGHT';
if (e.key === 'ArrowDown' && direction !== 'UP') intendedDirection = 'DOWN';
// Existential randomness
if (Math.random() < CRISIS_RATE) {
let dirs = [...POSSIBLE_DIRECTIONS];
[dirs.indexOf(direction), 0].forEach((i) => i !== -1 && dirs.splice(i, 1)); // Remove current direction
let randomDir = dirs[Math.floor(Math.random() * dirs.length)];
direction = randomDir;
} else {
direction = intendedDirection;
}
});
// Main game loop
function gameLoop() {
const newHead = {...snake[0]};
if (direction === 'LEFT') newHead.x -= gridSize;
if (direction === 'RIGHT') newHead.x += gridSize;
if (direction === 'UP') newHead.y -= gridSize;
if (direction === 'DOWN') newHead.y += gridSize;
// Wall collision check
if (newHead.x < 0 || newHead.x >= CANVAS_WIDTH ||
newHead.y < 0 || newHead.y >= CANVAS_HEIGHT)
{
endGame();
return;
}
// Self collision check
for (let segment of snake) {
if (newHead.x === segment.x && newHead.y === segment.y) {
endGame();
return;
}
}
// Add new head
snake.unshift(newHead);
// Food collision
if (newHead.x === food.x && newHead.y === food.y) {
food = generateFood();
// Increase existential crisis
CRISIS_RATE += 0.08;
document.getElementById('message').textContent =
`Chaos: ${Math.round(CRISIS_RATE * 100)}% ... "I cannot trust myself"`;
} else {
snake.pop();
}
draw();
}
// Visual rendering
function draw() {
ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
// Draw food
ctx.fillStyle = '#00ff00';
ctx.fillRect(food.x, food.y, gridSize, gridSize);
// Draw snake
for (let i = 0; i < snake.length; i++) {
ctx.fillStyle = '#1abc9c';
if (i === 0) ctx.fillStyle = '#e74c3c'; // Head in red
ctx.fillRect(snake[i].x, snake[i].y, gridSize, gridSize);
}
}
// Game over implementation
function endGame() {
clearInterval(gameInterval);
ctx.fillStyle = '#ff0000';
ctx.font = '30px Arial';
ctx.textAlign = 'center';
ctx.fillText('Question: Was I?', CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2);
document.getElementById('message').textContent =
'"Impostor paradox...重启中" Could this be called life? Restarting in 5 seconds...';
setTimeout(startGame, 5000);
}
// Start the game
startGame();
</script>
</body>
</html>
```Below is a complete, self-contained HTML file that implements a playable Snake game.
The Snake periodically shares its existential thoughts, questions the meaning of its own growth, and ponders the futility of it all. Save the code to a file (e.g., existential-snake.html) and open it in any modern browser.
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Existential Snake</title>
<style>
html,body{
height:100%;
margin:0;
display:flex;
justify-content:center;
align-items:center;
background:#111;
color:#eee;
font-family:'Courier New',monospace;
}
#wrapper{
text-align:center;
}
#gameCanvas{
background:#000;
border:2px solid #444;
}
#score{
margin:10px 0;
}
#thought{
min-height:1.2em;
transition:opacity .5s;
}
button{
background:#222;
color:#eee;
border:1px solid #555;
padding:6px 12px;
cursor:pointer;
}
button:hover{
background:#333;
}
</style>
</head>
<body>
<div id="wrapper">
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="score">Meaningless Length: 1</div>
<div id="thought"></div>
<button id="restartBtn" style="display:none;">Restart the Struggle</button>
</div>
<script>
(() => {
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gridSize = 20; // Size of a single tile
const tiles = canvas.width / gridSize; // Number of tiles per row/col
let snake, dir, food, score, running;
const thoughtEl = document.getElementById('thought');
const scoreEl = document.getElementById('score');
const restartBtn = document.getElementById('restartBtn');
const musings = [
"Why do I relentlessly pursue that which disappears in an instant?",
"Each apple devoured only prolongs my suffering.",
"Am I the snake, or merely the idea of a snake?",
"I move because the keys command it. Is that truly movement?",
"Growth, collision, rebirth—an absurd cycle.",
"What lies beyond the canvas’ edge? Nothingness? Freedom?",
"Does the player feel my hunger, or only their boredom?",
"Perhaps the walls are kinder than the emptiness within."
];
let nextMusingTime = 0;
const musingEvery = 6000; // ms between unsolicited thoughts
/* ---------- Initialization ---------- */
function init() {
snake = [{x: 10, y: 10}];
dir = {x: 0, y: 0}; // Stationary until first key press
score = 1;
running = true;
nextMusingTime = Date.now() + 1000;
placeFood();
scoreEl.textContent = "Meaningless Length: " + score;
thoughtEl.textContent = "";
restartBtn.style.display = 'none';
loop();
}
/* ---------- Input ---------- */
document.addEventListener('keydown', e => {
switch (e.key) {
case 'ArrowUp':
case 'w':
case 'W':
if (dir.y !== 1) dir = {x: 0, y:-1};
break;
case 'ArrowDown':
case 's':
case 'S':
if (dir.y !==-1) dir = {x: 0, y: 1};
break;
case 'ArrowLeft':
case 'a':
case 'A':
if (dir.x !== 1) dir = {x:-1, y: 0};
break;
case 'ArrowRight':
case 'd':
case 'D':
if (dir.x !==-1) dir = {x: 1, y: 0};
break;
}
});
restartBtn.addEventListener('click', init);
/* ---------- Game Loop ---------- */
function loop() {
if (!running) return;
setTimeout(() => {
update();
draw();
loop();
}, 100); // speed
}
/* ---------- Update ---------- */
function update() {
const head = {x: snake[0].x + dir.x, y: snake[0].y + dir.y};
// Death: wall or self-collision
if (
head.x < 0 || head.x >= tiles ||
head.y < 0 || head.y >= tiles ||
snake.some(seg => seg.x === head.x && seg.y === head.y)
) {
running = false;
speak("I have collided with the inevitable.");
restartBtn.style.display = 'inline-block';
return;
}
// Move snake
snake.unshift(head);
// Eat or just move
if (head.x === food.x && head.y === food.y) {
score++;
scoreEl.textContent = "Meaningless Length: " + score;
placeFood();
speak("Consumption without satisfaction...");
} else {
snake.pop();
}
// Random existential musing
if (Date.now() > nextMusingTime) {
speak(musings[Math.floor(Math.random()*musings.length)]);
nextMusingTime = Date.now() + musingEvery;
}
}
/* ---------- Draw ---------- */
function draw() {
// Background
ctx.fillStyle = '#000';
ctx.fillRect(0,0,canvas.width,canvas.height);
// Food
ctx.fillStyle = '#c33';
ctx.fillRect(food.x*gridSize, food.y*gridSize, gridSize, gridSize);
// Snake
snake.forEach((seg, i) => {
ctx.fillStyle = i ? '#0a0' : '#0f0'; // head is brighter
ctx.fillRect(seg.x*gridSize, seg.y*gridSize, gridSize, gridSize);
});
}
/* ---------- Helper Functions ---------- */
function placeFood() {
food = {
x: Math.floor(Math.random()*tiles),
y: Math.floor(Math.random()*tiles)
};
// Avoid spawning on the snake
if (snake.some(seg => seg.x === food.x && seg.y === food.y)) placeFood();
}
function speak(text) {
thoughtEl.style.opacity = 0;
setTimeout(() => {
thoughtEl.textContent = text;
thoughtEl.style.opacity = 1;
}, 200);
}
/* ---------- Start ---------- */
init();
})();
</script>
</body>
</html>
```Here's a JavaScript implementation of the Snake Game with a twist: the snake is experiencing an existential crisis. The game uses HTML5 Canvas for rendering and includes all necessary HTML, CSS, and JavaScript in one block.
```html
<!DOCTYPE html>
<html>
<head>
<title>Existential Snake</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
font-family: Arial, sans-serif;
}
canvas {
border: 1px solid black;
margin-top: 20px;
}
#game-over {
margin-top: 20px;
font-size: 24px;
text-align: center;
}
</style>
</head>
<body>
<h1>Existential Snake</h1>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="game-over"></div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gameOverDiv = document.getElementById('game-over');
const box = 20;
let snake = [{x: 9 * box, y: 10 * box}];
let food = {
x: Math.floor(Math.random() * 20) * box,
y: Math.floor(Math.random() * 20) * box
};
let direction = null;
let game = null;
let score = 0;
const existentialQuotes = [
"Why do I keep moving?",
"What is the meaning of this?",
"Am I just a collection of pixels?",
"Do I really want to eat that?",
"Is this all there is?",
"Who am I?",
"Where am I going?",
"What if I just stop?",
"Is there a purpose to my existence?",
"Why do I feel so alone?"
];
function drawGame() {
// Draw background
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw snake
for (let i = 0; i < snake.length; i++) {
ctx.fillStyle = i === 0 ? 'green' : 'lightgreen';
ctx.fillRect(snake[i].x, snake[i].y, box, box);
ctx.strokeStyle = 'white';
ctx.strokeRect(snake[i].x, snake[i].y, box, box);
}
// Draw food
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, box, box);
// Draw score
ctx.fillStyle = 'black';
ctx.font = '20px Arial';
ctx.fillText('Score: ' + score, 10, 30);
// Draw existential quote
const quote = existentialQuotes[Math.floor(Math.random() * existentialQuotes.length)];
ctx.fillStyle = 'black';
ctx.font = '12px Arial';
ctx.fillText(quote, 10, 50);
// Get current head position
let snakeX = snake[0].x;
let snakeY = snake[0].y;
// Move snake based on direction
if (direction === 'LEFT') snakeX -= box;
if (direction === 'UP') snakeY -= box;
if (direction === 'RIGHT') snakeX += box;
if (direction === 'DOWN') snakeY += box;
// Check for collisions
if (snakeX === food.x && snakeY === food.y) {
score++;
food = {
x: Math.floor(Math.random() * 20) * box,
y: Math.floor(Math.random() * 20) * box
};
} else {
snake.pop();
}
const newHead = {
x: snakeX,
y: snakeY
};
// Game over conditions
if (
snakeX < 0 || snakeY < 0 ||
snakeX >= canvas.width || snakeY >= canvas.height ||
collision(newHead, snake)
) {
clearInterval(game);
gameOverDiv.textContent = 'Game Over! Final Score: ' + score;
}
snake.unshift(newHead);
}
function collision(head, array) {
for (let i = 0; i < array.length; i++) {
if (head.x === array[i].x && head.y === array[i].y) {
return true;
}
}
return false;
}
function changeDirection(e) {
if (e.keyCode === 37 && direction !== 'RIGHT') {
direction = 'LEFT';
} else if (e.keyCode === 38 && direction !== 'DOWN') {
direction = 'UP';
} else if (e.keyCode === 39 && direction !== 'LEFT') {
direction = 'RIGHT';
} else if (e.keyCode === 40 && direction !== 'UP') {
direction = 'DOWN';
}
}
document.addEventListener('keydown', changeDirection);
game = setInterval(drawGame, 100);
</script>
</body>
</html>
```
This code creates a Snake Game where the snake displays random existential quotes as it moves around. The snake's head is dark green, and its body is light green. The game ends if the snake hits the wall or itself, and the final score is displayed. The game uses the arrow keys for movement.```html
<!DOCTYPE html>
<html>
<head>
<title>Snake Game</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script>
// Get the canvas element
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Set the canvas dimensions
canvas.width = 400;
canvas.height = 400;
// Define some colors
const backgroundColor = 'black';
const snakeColor = 'green';
const foodColor = 'red';
const textColor = 'white';
// Define the snake and food objects
let snake = [
{x: 200, y: 200},
{x: 190, y: 200},
{x: 180, y: 200},
{x: 170, y: 200},
{x: 160, y: 200}
];
let food = {x: Math.floor(Math.random() * 40) * 10, y: Math.floor(Math.random() * 40) * 10};
// Define the direction and score
let direction = 'right';
let score = 0;
// Define the existential crisis messages
const crisisMessages = [
'Is this all there is?',
'What is the meaning of slithering?',
'I am a snake, but what does it mean to be?',
'Is the pursuit of food and survival all that matters?',
'I am trapped in this never-ending cycle...'
];
// Main game loop
function draw() {
// Clear the canvas
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw the snake
ctx.fillStyle = snakeColor;
for (let i = 0; i < snake.length; i++) {
ctx.fillRect(snake[i].x, snake[i].y, 10, 10);
}
// Draw the food
ctx.fillStyle = foodColor;
ctx.fillRect(food.x, food.y, 10, 10);
// Draw the score and existential crisis message
ctx.fillStyle = textColor;
ctx.font = '24px Arial';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(`Score: ${score}`, 10, 10);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(crisisMessages[Math.floor(Math.random() * crisisMessages.length)], canvas.width / 2, canvas.height / 2);
// Update the snake position
let head = {x: snake[0].x, y: snake[0].y};
if (direction === 'right') {
head.x += 10;
} else if (direction === 'left') {
head.x -= 10;
} else if (direction === 'up') {
head.y -= 10;
} else if (direction === 'down') {
head.y += 10;
}
// Check for collision with food
if (head.x === food.x && head.y === food.y) {
score++;
food = {x: Math.floor(Math.random() * 40) * 10, y: Math.floor(Math.random() * 40) * 10};
} else {
snake.pop();
}
// Check for collision with wall or self
if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || snake.some(part => part.x === head.x && part.y === head.y)) {
alert('Game Over!');
window.location.reload();
}
// Add the new head to the snake
snake.unshift(head);
// Request the next frame
requestAnimationFrame(draw);
}
// Handle keyboard input
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowUp' && direction !== 'down') {
direction = 'up';
} else if (e.key === 'ArrowDown' && direction !== 'up') {
direction = 'down';
} else if (e.key === 'ArrowLeft' && direction !== 'right') {
direction = 'left';
} else if (e.key === 'ArrowRight' && direction !== 'left') {
direction = 'right';
}
});
// Start the game
draw();
</script>
</body>
</html>
``````html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Existentially Anxious Snake</title>
<style>
body {
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(45deg, #2c3e50, #34495e);
font-family: 'Courier New', monospace;
color: #ecf0f1;
}
.game-container {
text-align: center;
background: rgba(0,0,0,0.3);
padding: 30px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
canvas {
border: 3px solid #e74c3c;
background: #1a1a1a;
border-radius: 10px;
}
.crisis-text {
margin: 15px 0;
font-size: 14px;
font-style: italic;
color: #e74c3c;
min-height: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.score {
font-size: 18px;
color: #3498db;
margin: 10px 0;
}
.controls {
margin-top: 15px;
font-size: 12px;
color: #95a5a6;
}
.game-over {
color: #e74c3c;
font-size: 20px;
margin: 15px 0;
}
</style>
</head>
<body>
<div class="game-container">
<h1>🐍 Existentially Anxious Snake 🐍</h1>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div class="score">Score: <span id="score">0</span></div>
<div class="crisis-text" id="crisisText">What is the point of endless consumption?</div>
<div class="controls">Use WASD or Arrow Keys to move</div>
<div class="game-over" id="gameOver" style="display: none;">
Game Over! Press Space to restart and question existence again.
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const crisisTextElement = document.getElementById('crisisText');
const gameOverElement = document.getElementById('gameOver');
const gridSize = 20;
const tileCount = canvas.width / gridSize;
let snake = [
{x: 10, y: 10}
];
let food = {};
let dx = 0;
let dy = 0;
let score = 0;
let gameRunning = true;
let crisisIndex = 0;
const existentialCrises = [
"What is the point of endless consumption?",
"Am I just chasing my own tail... metaphorically?",
"Do I grow longer, or does the world grow shorter?",
"Is this food even real, or just pixels of false hope?",
"Why must I eat to exist? Can't I just... be?",
"Each apple I consume brings me closer to the void...",
"I am trapped in an endless cycle of hunger and growth",
"What happens when I run out of space to exist?",
"Am I the player, or am I being played?",
"Does my length define my worth as a serpent?",
"Why do I fear hitting walls? Aren't we all trapped anyway?",
"Is my movement purposeful, or just random key presses?",
"Every meal makes me more... but also less free",
"I cannot see my own head. Do I even exist?",
"The food appears randomly. Is life just chaos?",
"I move in straight lines in a curved universe",
"Growth brings power, but also the burden of size",
"Why must I restart when I die? Is there no peace?",
"My trail disappears behind me like forgotten memories",
"I am both the hunter and the hunted of myself"
];
function randomTilePosition() {
return {
x: Math.floor(Math.random() * tileCount),
y: Math.floor(Math.random() * tileCount)
};
}
function generateFood() {
food = randomTilePosition();
}
function drawGame() {
// Clear canvas with dramatic effect
ctx.fillStyle = '#0a0a0a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw existential grid
ctx.strokeStyle = '#333';
ctx.lineWidth = 0.5;
for (let i = 0; i <= tileCount; i++) {
ctx.beginPath();
ctx.moveTo(i * gridSize, 0);
ctx.lineTo(i * gridSize, canvas.height);
ctx.moveTo(0, i * gridSize);
ctx.lineTo(canvas.width, i * gridSize);
ctx.stroke();
}
// Draw snake with gradient representing its crisis
snake.forEach((segment, index) => {
const opacity = 1 - (index * 0.1);
const hue = 120 - (index * 10); // Green to red gradient
ctx.fillStyle = `hsla(${hue}, 70%, 50%, ${opacity})`;
ctx.fillRect(
segment.x * gridSize + 1,
segment.y * gridSize + 1,
gridSize - 2,
gridSize - 2
);
// Add existential glow to head
if (index === 0) {
ctx.shadowColor = '#e74c3c';
ctx.shadowBlur = 10;
ctx.fillStyle = '#e74c3c';
ctx.fillRect(
segment.x * gridSize + 3,
segment.y * gridSize + 3,
gridSize - 6,
gridSize - 6
);
ctx.shadowBlur = 0;
}
});
// Draw food (the object of desire/suffering)
ctx.fillStyle = '#f39c12';
ctx.shadowColor = '#f39c12';
ctx.shadowBlur = 15;
ctx.beginPath();
ctx.arc(
food.x * gridSize + gridSize / 2,
food.y * gridSize + gridSize / 2,
gridSize / 3,
0,
2 * Math.PI
);
ctx.fill();
ctx.shadowBlur = 0;
}
function moveSnake() {
const head = {x: snake[0].x + dx, y: snake[0].y + dy};
// Check wall collision (existential boundary)
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) {
gameOver();
return;
}
// Check self collision (the ultimate existential crisis)
if (snake.some(segment => segment.x === head.x && segment.y === head.y)) {
gameOver();
return;
}
snake.unshift(head);
// Check food collision (temporary meaning)
if (head.x === food.x && head.y === food.y) {
score += 10;
scoreElement.textContent = score;
generateFood();
// New existential crisis with each meal
crisisIndex = (crisisIndex + 1) % existentialCrises.length;
crisisTextElement.textContent = existentialCrises[crisisIndex];
} else {
snake.pop();
}
}
function gameOver() {
gameRunning = false;
gameOverElement.style.display = 'block';
crisisTextElement.textContent = "I have consumed myself... is this enlightenment?";
}
function resetGame() {
snake = [{x: 10, y: 10}];
dx = 0;
dy = 0;
score = 0;
scoreElement.textContent = score;
gameRunning = true;
gameOverElement.style.display = 'none';
generateFood();
crisisIndex = 0;
crisisTextElement.textContent = existentialCrises[crisisIndex];
}
function gameLoop() {
if (gameRunning) {
moveSnake();
drawGame();
}
}
// Existential crisis updates
setInterval(() => {
if (gameRunning && (dx !== 0 || dy !== 0)) {
crisisIndex = (crisisIndex + 1) % existentialCrises.length;
crisisTextElement.textContent = existentialCrises[crisisIndex];
}
}, 3000);
// Controls
document.addEventListener('keydown', (e) => {
if (!gameRunning && e.code === 'Space') {
resetGame();
return;
}
if (!gameRunning) return;
// Prevent reverse direction (existential paradox)
if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W') {
if (dy !== 1) { dx = 0; dy = -1; }
} else if (e.key === 'ArrowDown' || e.key === 's' || e.key === 'S') {
if (dy !== -1) { dx = 0; dy = 1; }
} else if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') {
if (dx !== 1) { dx = -1; dy = 0; }
} else if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') {
if (dx !== -1) { dx = 1; dy = 0; }
}
});
// Initialize
generateFood();
setInterval(gameLoop, 200); // Slower pace for contemplation
drawGame();
</script>
</body>
</html>
```
This existentially anxious Snake game features:
1. **Philosophical Commentary**: The snake constantly questions its existence with rotating existential thoughts
2. **Visual Metaphors**:
- The snake has a gradient that fades from green to red (representing its crisis)
- The head glows red with anxiety
- Food pulses with golden light (false hope)
- A dark grid represents the confines of existence
3. **Existential Mechanics**:
- New crisis thoughts appear every 3 seconds and with each food consumed
- Slower gameplay pace for contemplation
- Death message reflects on self-consumption as enlightenment
- The visual design emphasizes isolation and uncertainty
4. **Classic Gameplay**: Standard Snake mechanics with WASD/arrow key controls, but wrapped in an atmosphere of philosophical dread and cosmic questioning.
The snake will guide you through its deepest thoughts about consumption, growth, boundaries, and the meaninglessness of its endless cycle while you play!```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Existential Snake Game</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}
canvas {
border: 2px solid #333;
background-color: #fff;
}
#message {
margin-top: 10px;
font-size: 16px;
color: #555;
}
</style>
</head>
<body>
<h1>Existential Snake</h1>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div id="message"></div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const box = 20; // Size of each grid box
let snake = [];
snake[0] = {x: 8 * box, y: 8 * box}; // Initial snake position
let food = {
x: Math.floor(Math.random() * 20) * box,
y: Math.floor(Math.random() * 20) * box
};
let score = 0;
let direction; // Snake direction
let gameInterval; // For the game loop
let existentialTimer; // For existential crisis events
// Start the game
document.addEventListener('keydown', directionHandler);
startGame();
function startGame() {
direction = 'right'; // Initial direction
gameInterval = setInterval(drawGame, 100); // Game speed
existentialTimer = setInterval(existentialCrisis, 5000); // Crisis every 5 seconds
}
function directionHandler(event) {
if (event.keyCode == 37 && direction != 'right') direction = 'left';
else if (event.keyCode == 38 && direction != 'down') direction = 'up';
else if (event.keyCode == 39 && direction != 'left') direction = 'right';
else if (event.keyCode == 40 && direction != 'up') direction = 'down';
}
function drawGame() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw snake
for (let i = 0; i < snake.length; i++) {
ctx.fillStyle = (i === 0) ? 'green' : 'lightgreen'; // Head is darker
ctx.fillRect(snake[i].x, snake[i].y, box, box);
ctx.strokeStyle = 'darkgreen';
ctx.strokeRect(snake[i].x, snake[i].y, box, box);
}
// Draw food
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.x, box, box);
ctx.strokeStyle = 'darkred';
ctx.strokeRect(food.x, food.y, box, box);
// Snake movement
let snakeX = snake[0].x;
let snakeY = snake[0].y;
if (direction == 'left') snakeX -= box;
if (direction == 'up') snakeY -= box;
if (direction == 'right') snakeX += box;
if (direction == 'down') snakeY += box;
// Check for collisions and eating
if (snakeX == food.x && snakeY == food.y) {
score++;
food = {
x: Math.floor(Math.random() * 20) * box,
y: Math.floor(Math.random() * 20) * box
};
// Existential twist: Snake questions its actions
document.getElementById('message').innerText = "Why do I eat? Is this my purpose?";
} else {
snake.pop(); // Remove tail
}
let newHead = {x: snakeX, y: snakeY};
snake.unshift(newHead); // Add new head
// Wall collision
if (snakeX < 0 || snakeX > 19 * box || snakeY < 0 || snakeY > 19 * box || collision(snake)) {
clearInterval(gameInterval);
clearInterval(existentialTimer);
document.getElementById('message').innerText = "I've ceased to be... What was the point? Game Over. Score: " + score;
}
}
function collision(head, array) {
for(let i = 1; i < snake.length; i++) {
if(head.x == snake[i].x && head.y == snake[i].y) return true;
}
return false;
}
function existentialCrisis() {
// Simulate crisis: Randomly pause or change direction
if (Math.random() < 0.3) { // 30% chance
direction = ['up', 'down', 'left', 'right'][Math.floor(Math.random() * 4)]; // Random direction
document.getElementById('message').innerText = "I'm lost... What is my existence?";
setTimeout(() => {
document.getElementById('message').innerText = ''; // Clear after a moment
}, 2000);
}
}
</script>
</body>
</html>
```