Skip to content

Instantly share code, notes, and snippets.

@Incipiens
Created June 16, 2026 09:14
Show Gist options
  • Select an option

  • Save Incipiens/9f5b39c3ce07f51fea19800fc764885f to your computer and use it in GitHub Desktop.

Select an option

Save Incipiens/9f5b39c3ce07f51fea19800fc764885f to your computer and use it in GitHub Desktop.
Full DiffusionGemma output - XDA

Make a Flappy Bird game in Python, rendered via my web browser and served with Flask

<|channel>thought Flappy Bird game. Python. Flask. Web browser (HTML/CSS/JS).

*   *Backend:* Flask (Python) to serve the HTML file and static assets.
*   *Frontend:* HTML5 Canvas for rendering, JavaScript for game logic (physics, collision, input handling). This is crucial because real-time games like Flappy Bird are best handled on the client side to avoid latency issues, while Flask acts as the server.

*   `app.py`: The Flask server.
*   `templates/index.html`: The main structure.
*   `static/style.css`: Styling for centering the game.
*   `static/game.js`: The game engine logic.

*   *Step 1: Flask Setup (`app.py`)*
    *   Import Flask.
    *   Define a route for `/` that returns `index.html`.

*   *Step 2: HTML (`templates/index.html`)*
    *   Need a `<canvas>` element.
    *   Link the CSS and JS files.

*   *Step 3: CSS (`static/style.css`)*
    *   Center the canvas.
    *   Give a border.

*   *Step 4: JavaScript Logic (`static/game.js` - The hardest part)*
    *   *Variables:* Bird (x, y, velocity, gravity), Pipes (array of objects), Score, Game State.
    *   *Game Loop:* `requestAnimationFrame`.
    *   *Physics:* Gravity pulls bird down, jump on click.
    *   *Pipes:* Generate random height, move left, remove when off screen.
    *   *Collision:* Check if bird hits pipes, floor, or ceiling.
    *   *Drawing:* Draw bird and pipes every frame.

*   *Bird:* A square (for simplicity) or a circle.
*   *Pipes:* Rectangles with a gap.
*   *Input:* `Space` bar or `click`.

*   *Issue:* If I just write a basic loop, it might be too fast on different monitors.
*   *Fix:* Use a delta time or a fixed-step interval approach to ensure the game runs at the same speed regardless of refresh rate.
*   *Issue:* Collision detection can be tricky.
*   *Fix:* Use simple axis-aligned bounding box (AABB) logic.<channel|>To create a Flappy Bird game served via Flask, we will use **Flask** as the web server and **HTML5 Canvas with JavaScript** for the game engine. Real-time game logic is best handled on the client-side (JS) to prevent input lag, while Python handles serving the files.

Here is the complete folder structure and the code to get it running.

Project Structure

flappy_bird/
│   app.py
├── templates/
│   └── index.html
└── static/
    ├── style.css
    └── game.js

1. The Flask Server (app.py)

This script initializes the server and serves our HTML page.

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True)

2. The HTML Template (templates/index.html)

This sets up the canvas where the game will be drawn.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flappy Bird Flask</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
    <div id="game-container">
        <canvas id="gameCanvas" width="320" height="480"></canvas>
    </div>
    <script src="{{ url_for('static', filename='game.js') }}"></script>
</body>
</html>

3. The Styling (static/style.css)

This centers the game on your screen.

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #223;
    font-family: Arial, sans-serif;
}

#game-container {
    border: 5px solid #fff;
}

canvas {
    background-color: #70c5ce;
    display: block;
}

4. The Game Logic (static/game.js)

This handles the physics, collisions, and rendering.

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

// Game variables
let bird = {
    x: 50,
    y: 150,
    width: 20,
    height: 20,
    gravity: 0.6,
    jump: -10,
    velocity: 0
};

let pipes = [];
let pipeWidth = 50;
let pipeGap = 120;
let frameCount = 0;
let score = 0;
let gameOver = false;

// Controls
document.addEventListener('keydown', (e) => {
    if (e.code === 'Space') flap();
    if (gameOver) resetGame();
});

canvas.addEventListener('mousedown', flap);

function flap() {
    if (gameOver) {
        resetGame();
    } else {
        bird.velocity = bird.jump;
    }
}

function resetGame() {
    bird.y = 150;
    bird.velocity = 0;
    pipes = [];
    score = 0;
    frameCount = 0;
    gameOver = false;
    loop();
}

function createPipe() {
    let minHeight = 50;
    let maxHeight = canvas.height - pipeGap - minHeight;
    let height = Math.floor(Math.random() * (maxHeight - minHeight + 1)) + minHeight;
    pipes.push({
        x: canvas.width,
        top: height,
        bottom: canvas.height - height - pipeGap
    });
}

function update() {
    if (gameOver) return;

    bird.velocity += bird.gravity;
    bird.y += bird.velocity;

    // Pipe logic
    if (frameCount % 90 === 0) {
        createPipe();
    }

    for (let i = 0; i < pipes.length; i++) {
        pipes[i].x -= 2;

        // Collision detection
        if (
            bird.x + bird.width > pipes[i].x &&
            bird.x < pipes[i].x + pipeWidth &&
            (bird.y < pipes[i].top || bird.y + bird.height > canvas.height - pipes[i].bottom)
        ) {
            gameOver = true;
        }

        if (pipes[i].x + pipeWidth < 0) {
            pipes.shift();
            score++;
        }
    }

    // Floor and Ceiling collision
    if (bird.y + bird.height > canvas.height || bird.y < 0) {
        gameOver = true;
    }

    frameCount++;
}

function draw() {
    // Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Draw Bird
    ctx.fillStyle = "yellow";
    ctx.fillRect(bird.x, bird.y, bird.width, bird.height);

    // Draw Pipes
    ctx.fillStyle = "green";
    pipes.forEach(pipe => {
        // Top pipe
        ctx.fillRect(pipe.x, 0, pipeWidth, pipe.top);
        // Bottom pipe
        ctx.fillRect(pipe.x, canvas.height - pipe.bottom, pipeWidth, pipe.bottom);
    });

    // Draw Score
    ctx.fillStyle = "white";
    ctx.font = "20px Arial";
    ctx.fillText(`Score: ${score}`, 10, 25);

    if (gameOver) {
        ctx.fillStyle = "rgba(0,0,0,0.5)";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "white";
        ctx.fillText("GAME OVER", 80, 240);
        ctx.fillText("Press Space to Restart", 70, 270);
    }
}

function loop() {
    update();
    draw();
    if (!gameOver) {
        requestAnimationFrame(loop);
    }
}

loop();

How to run it

  1. Install Flask:
    pip install flask
  2. Create the files: Organize the code into the folder structure shown at the top.
  3. Run the app:
    python app.py
  4. Play: Open your web browser and go to http://127.0.0.1:5000.

How to play:

  • Spacebar or Click to jump.
  • Avoid the green pipes.
  • Press Space to restart after losing.

total time: 137895.79ms, time per step: 1121.10ms (123 steps over 9 blocks, entropy-bound)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment