Skip to content

Instantly share code, notes, and snippets.

@mojoaxel
Created February 6, 2025 06:19
Show Gist options
  • Save mojoaxel/d4e1c95220816fd3eb89cfd1906aca52 to your computer and use it in GitHub Desktop.
Save mojoaxel/d4e1c95220816fd3eb89cfd1906aca52 to your computer and use it in GitHub Desktop.
Flapp-Bird like game create by "Anthropic: Claude 3.5 Sonnet (2024-06-20) (self-moderated)" - CC-0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Emoji Flappy Ball</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; }
body { font-family: Arial, sans-serif; background-color: #87CEEB; touch-action: manipulation; }
#game-container { width: 100%; height: 100%; position: relative; overflow: hidden; background-color: #4AA7FF; }
#ball { position: absolute; font-size: 30px; user-select: none; }
.pipe { position: absolute; width: 15%; background-color: #444444; }
#score { position: fixed; top: 10px; left: 50%; transform: translateX(-50%); font-size: 36px; font-weight: bold; color: white; z-index: 10; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); }
#game-over, #start-prompt { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: white; z-index: 20; }
#game-over { display: none; background-color: rgba(0, 0, 0, 0.7); width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="game-container">
<div id="ball">🏐</div>
<div id="score">0</div>
<div id="game-over">
<div>Game Over</div>
<div>Score: <span id="final-score"></span></div>
</div>
<div id="start-prompt">Click or tap to start<br>Double-click or double-tap to jump higher</div>
</div>
<script>
// DOM elements
const gameContainer = document.getElementById('game-container');
const ball = document.getElementById('ball');
const scoreElement = document.getElementById('score');
const gameOverElement = document.getElementById('game-over');
const finalScoreElement = document.getElementById('final-score');
const startPrompt = document.getElementById('start-prompt');
// Game variables
let ballY, ballVelocity, score, pipes, gameLoop, gameOver, gameStarted;
let containerWidth, containerHeight;
let gameSpeed = 1;
let pipeSpacing = 0.5;
// Constants
const JUMP_STRENGTH = 0.007;
const GRAVITY = 0.5;
const PIPE_WIDTH = 0.15;
const INITIAL_GAP = 0.35;
const MIN_GAP = 0.2;
const MIN_PIPE_SPACING = 0.3;
function initGame() {
// Reset game state
containerWidth = gameContainer.clientWidth;
containerHeight = gameContainer.clientHeight;
ballY = containerHeight / 2;
ballVelocity = 0;
score = 0;
pipes = [];
gameOver = false;
gameStarted = false;
gameSpeed = 1;
pipeSpacing = 0.5;
// Reset UI
scoreElement.textContent = score;
gameOverElement.style.display = 'none';
startPrompt.style.display = 'block';
document.querySelectorAll('.pipe').forEach(pipe => pipe.remove());
// Position ball
ball.style.left = '10%';
ball.style.top = ballY + 'px';
// Start game loop
cancelAnimationFrame(gameLoop);
update();
}
function update() {
if (gameOver) return;
if (gameStarted) {
// Update ball position
ballVelocity += GRAVITY * gameSpeed;
ballY += ballVelocity;
ball.style.top = ballY + 'px';
// Check for collisions
if (ballY < 0 || ballY > containerHeight - 30) {
endGame();
}
// Create new pipe if needed
if (pipes.length === 0 || pipes[pipes.length - 1].x < containerWidth * pipeSpacing) {
createPipe();
}
// Update pipes
pipes.forEach(pipe => {
pipe.x -= containerWidth * 0.003 * gameSpeed;
pipe.topPipe.style.left = pipe.bottomPipe.style.left = pipe.x + 'px';
if (pipe.x < -containerWidth * PIPE_WIDTH) {
gameContainer.removeChild(pipe.topPipe);
gameContainer.removeChild(pipe.bottomPipe);
pipes.shift();
updateScore();
}
if (checkCollision(pipe)) {
endGame();
}
});
}
gameLoop = requestAnimationFrame(update);
}
function createPipe() {
const gap = Math.max(containerHeight * (INITIAL_GAP - (score * 0.002)), containerHeight * MIN_GAP);
const topHeight = Math.random() * (containerHeight - gap - 100) + 50;
const bottomHeight = containerHeight - topHeight - gap;
const createPipeElement = (height, position) => {
const pipe = document.createElement('div');
pipe.className = 'pipe';
pipe.style[position] = '0';
pipe.style.height = height + 'px';
return pipe;
};
const topPipe = createPipeElement(topHeight, 'top');
const bottomPipe = createPipeElement(bottomHeight, 'bottom');
gameContainer.appendChild(topPipe);
gameContainer.appendChild(bottomPipe);
pipes.push({ x: containerWidth, topPipe, bottomPipe });
}
function checkCollision(pipe) {
const ballRect = ball.getBoundingClientRect();
const topPipeRect = pipe.topPipe.getBoundingClientRect();
const bottomPipeRect = pipe.bottomPipe.getBoundingClientRect();
return (
ballRect.right > topPipeRect.left &&
ballRect.left < topPipeRect.right &&
(ballRect.top < topPipeRect.bottom || ballRect.bottom > bottomPipeRect.top)
);
}
function updateScore() {
score++;
scoreElement.textContent = score;
// Increase difficulty
gameSpeed = 1 + (score / 25); // Linear increase, double speed at score 25
pipeSpacing = Math.max(MIN_PIPE_SPACING, 0.5 - (score * 0.008)); // Decrease spacing, but not below minimum
}
function endGame() {
cancelAnimationFrame(gameLoop);
gameOver = true;
gameOverElement.style.display = 'flex';
finalScoreElement.textContent = score;
setTimeout(initGame, 3000);
}
function jump(strength = 1) {
if (!gameStarted) {
gameStarted = true;
startPrompt.style.display = 'none';
}
ballVelocity = -containerHeight * JUMP_STRENGTH * strength * gameSpeed;
}
// Event handling
let lastInteraction = 0;
function handleInteraction(e) {
e.preventDefault();
if (gameOver) return;
const currentTime = new Date().getTime();
const interactionLength = currentTime - lastInteraction;
jump(interactionLength < 300 && interactionLength > 0 ? 1.5 : 1);
lastInteraction = currentTime;
}
gameContainer.addEventListener('touchstart', handleInteraction);
gameContainer.addEventListener('mousedown', handleInteraction);
document.addEventListener('keydown', event => {
if (event.code === 'Space' && !gameOver) jump();
});
window.addEventListener('resize', initGame);
initGame();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment