Skip to content

Instantly share code, notes, and snippets.

@wwtv127
Created December 30, 2025 02:02
Show Gist options
  • Select an option

  • Save wwtv127/cbbb72ea0ece47734451d8b6bcb3eb76 to your computer and use it in GitHub Desktop.

Select an option

Save wwtv127/cbbb72ea0ece47734451d8b6bcb3eb76 to your computer and use it in GitHub Desktop.
R1 Artifact: My Project
<!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>Flappy R1</title>
<style>
body, html {
margin: 0;
padding: 0;
width: 240px;
height: 290px;
overflow: hidden;
background-color: #70c5ce;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
touch-action: none;
user-select: none;
-webkit-user-select: none;
}
#game-container {
position: relative;
width: 240px;
height: 290px;
overflow: hidden;
background: linear-gradient(#70c5ce, #4fb0ba);
}
#bird {
position: absolute;
width: 20px;
height: 16px;
background-color: #f7d302;
border: 2px solid #000;
border-radius: 4px;
left: 40px;
top: 137px; /* Center (290/2 - 8) */
z-index: 10;
will-change: transform;
transform: translateZ(0);
}
#bird::after {
content: '';
position: absolute;
right: 2px;
top: 2px;
width: 4px;
height: 4px;
background: black;
border-radius: 50%;
}
.pipe {
position: absolute;
width: 30px;
background-color: #73bf2e;
border: 2px solid #000;
z-index: 5;
will-change: transform;
transform: translateZ(0);
}
#score-display {
position: absolute;
top: 10px;
width: 100%;
text-align: center;
font-size: 24px;
font-weight: bold;
color: white;
text-shadow: 2px 2px #000;
z-index: 20;
pointer-events: none;
}
#overlay {
position: absolute;
top: 0;
left: 0;
width: 240px;
height: 290px;
background: rgba(0,0,0,0.7);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 30;
text-align: center;
}
.btn {
background: #ff4d00;
border: 2px solid white;
padding: 12px 24px;
color: white;
border-radius: 8px;
font-size: 18px;
font-weight: bold;
margin-top: 15px;
cursor: pointer;
box-shadow: 0 4px #992e00;
touch-action: manipulation;
}
.btn:active {
transform: translateY(2px);
box-shadow: 0 2px #992e00;
}
</style>
</head>
<body>
<div id="game-container">
<div id="score-display">0</div>
<div id="bird"></div>
<div id="overlay">
<h2 id="msg" style="margin: 0; font-size: 28px;">FLAPPY R1</h2>
<p style="margin: 5px 0;">Tap Screen to Fly</p>
<div class="btn" id="start-btn">START</div>
</div>
</div>
<script>
const bird = document.getElementById('bird');
const container = document.getElementById('game-container');
const scoreDisplay = document.getElementById('score-display');
const overlay = document.getElementById('overlay');
const msg = document.getElementById('msg');
const startBtn = document.getElementById('start-btn');
const GRAVITY = 0.22;
const FLAP = -4.0;
const SPAWN_RATE = 1600;
const PIPE_SPEED = 2;
const GAP = 95;
let birdY = 137;
let birdV = 0;
let score = 0;
let gameActive = false;
let pipes = [];
let lastTime = 0;
let spawnTimer = 0;
function resetGame() {
// Clean existing pipes
pipes.forEach(p => {
if (p.top && p.top.parentNode) p.top.remove();
if (p.bottom && p.bottom.parentNode) p.bottom.remove();
});
pipes = [];
birdY = 137;
birdV = 0;
score = 0;
spawnTimer = 0;
scoreDisplay.innerText = '0';
// Hide overlay
overlay.style.display = 'none';
// Final prep before loop
lastTime = performance.now();
gameActive = true;
requestAnimationFrame(gameLoop);
}
function createPipe() {
const minHeight = 40;
const availableSpace = 290 - GAP;
const topHeight = Math.floor(Math.random() * (availableSpace - 2 * minHeight)) + minHeight;
const topPipe = document.createElement('div');
topPipe.className = 'pipe';
topPipe.style.height = topHeight + 'px';
topPipe.style.top = '0';
topPipe.style.left = '240px';
const bottomPipe = document.createElement('div');
bottomPipe.className = 'pipe';
bottomPipe.style.height = (290 - topHeight - GAP) + 'px';
bottomPipe.style.bottom = '0';
bottomPipe.style.left = '240px';
container.appendChild(topPipe);
container.appendChild(bottomPipe);
pipes.push({
x: 240,
top: topPipe,
bottom: bottomPipe,
passed: false
});
}
function gameOver() {
gameActive = false;
msg.innerText = "GAME OVER";
overlay.style.display = 'flex';
}
function gameLoop(timestamp) {
if (!gameActive) return;
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
// Physics
birdV += GRAVITY;
birdY += birdV;
// Visuals
const rotation = Math.min(Math.max(birdV * 4, -25), 90);
bird.style.transform = `translateY(${birdY - 137}px) rotate(${rotation}deg)`;
// Collision: Floor/Ceiling
if (birdY < -10 || birdY > 280) {
gameOver();
return;
}
// Spawning
spawnTimer += deltaTime;
if (spawnTimer >= SPAWN_RATE) {
createPipe();
spawnTimer = 0;
}
// Pipe movement and logic
for (let i = pipes.length - 1; i >= 0; i--) {
let p = pipes[i];
p.x -= PIPE_SPEED;
p.top.style.transform = `translateX(${p.x - 240}px)`;
p.bottom.style.transform = `translateX(${p.x - 240}px)`;
// Collision Detection
if (p.x < 60 && p.x > 10) {
const topPipeBottom = parseInt(p.top.style.height);
const bottomPipeTop = 290 - parseInt(p.bottom.style.height);
if (birdY < topPipeBottom || (birdY + 16) > bottomPipeTop) {
gameOver();
return;
}
}
// Scoring
if (!p.passed && p.x < 40) {
p.passed = true;
score++;
scoreDisplay.innerText = score;
}
// GC
if (p.x < -40) {
p.top.remove();
p.bottom.remove();
pipes.splice(i, 1);
}
}
requestAnimationFrame(gameLoop);
}
// High compatibility button handling
const handleStart = (e) => {
e.preventDefault();
e.stopPropagation();
if (!gameActive) {
resetGame();
}
};
startBtn.addEventListener('touchstart', handleStart, { passive: false });
startBtn.addEventListener('mousedown', handleStart);
// Global tap for jumping
container.addEventListener('touchstart', (e) => {
if (gameActive) {
birdV = FLAP;
}
}, { passive: true });
// Fallback for mouse
container.addEventListener('mousedown', (e) => {
if (gameActive && e.target !== startBtn) {
birdV = FLAP;
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment