Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

4 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Chubby Bird: A Custom Reinforcement Learning Environment with a Trained DQN Agent

A production-grade reinforcement learning project showcasing Deep Q-Network (DQN) training in a custom 2D game environment. This repository demonstrates the complete ML pipeline: problem formulation, state/reward design, agent training, and competitive gameplay.

๐ŸŽฎ Project Demo

Chubby Bird AI Gameplay

Click the image to watch the trained DQN agent in action!

This video demonstrates the final trained agent interacting with the environment in real time.
You can observe decision making, food collection behavior, gravity handling, and failure cases learned through reinforcement learning.

๐Ÿ“Š Project Overview

Chubby Bird is not just a gameโ€”it's a reinforcement learning environment where an AI agent learns optimal decision-making through self-play. The agent learns to navigate a dynamic 2D space, collect time-sensitive targets, and maximize survival time.

Problem Statement

  • Environment: A 2D scrolling game with physics-based bird dynamics
  • Objective: Train an AI agent to catch falling food objects while avoiding ground collision
  • Challenge: Reward shaping and exploration-exploitation balance in a continuous action environment

Key Results

  • โœ… Agent learns to actively seek food (vs. passive survival strategies)
  • โœ… Achieves consistent food collection rates after 50 episodes
  • โœ… Beats untrained baseline in competitive gameplay
  • โœ… Trains in ~10 minutes on CPU

๐Ÿง  The Reinforcement Learning Problem

State Space (Observation)

The agent observes 4-dimensional state vector at each timestep:

State = [bird_y, bird_velocity, food_dx, food_dy]

โ€ข bird_y       : Bird's vertical position (normalized 0-1, 0=top, 1=bottom)
โ€ข bird_velocity: Current vertical velocity (normalized, range -1 to 1.5)
โ€ข food_dx      : Horizontal distance to nearest food (normalized -1 to 1)
โ€ข food_dy      : Vertical distance to nearest food (normalized -1 to 1)

Design Rationale: This minimal 4D representation captures the essential control problemโ€”vertical positioning and proximity awarenessโ€”without computational overhead.

Action Space (Control)

The agent has 2 discrete actions:

action = 0: Do nothing (gravity pulls bird down)
action = 1: Flap wings (apply upward impulse)

Design Rationale: Simple binary control mimics Flappy Bird constraints while remaining Markovian and deterministic.

Reward Design (Engineering Focus)

The reward function was carefully engineered to avoid local optima and reward hacking:

Trigger Reward Purpose
Collect food +10.0 Primary objective
Miss food (escape) -2.0 Penalize inaction
In safe middle region +0.1 Exploration incentive
At top of screen -2.0 Force downward diversity
Near ground -0.5 Discourage reckless play
Within 100px of food +0.05 Proximity guidance
Per step -0.005 Efficiency penalty

Critical Engineering Decisions:

  1. No inflated proximity bonus - Removed +0.5/step bonus (agent hovered near food without catching it)
  2. Only reward actual catches - Not generic "moving toward" (eliminated false positives)
  3. Random spawn positions - Prevents overfitting to starting in middle
  4. Score-based model saving - Save on food caught, not total reward (prevents reward gaming)

๐Ÿค– Agent Architecture

DQN Implementation

Deep Q-Network (DQN) Architecture:
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
Input Layer:     4 neurons (state dimensions)
Hidden Layer 1:  128 neurons + ReLU activation
Hidden Layer 2:  128 neurons + ReLU activation
Output Layer:    2 neurons (Q-values per action)

Training Configuration

Episodes:               50
Max steps/episode:      3000
Learning rate:          0.001 (Adam optimizer)
Discount factor (ฮณ):    0.99
Epsilon decay:          0.98 per episode (slower exploration decay)
Epsilon min:            0.10 (maintain 10% exploration)
Batch size:             64
Memory buffer:          5000 experiences
Target update freq:     200 steps

Stabilization Techniques

  1. Target Network Freezing: Separate frozen target network updated every 200 steps (prevents feedback loops)
  2. Gradient Clipping: clip_grad_norm_(max_norm=1.0) (prevents exploding gradients)
  3. Experience Replay: Mini-batch SGD from randomized memory buffer (breaks temporal correlations)

๐ŸŽฎ System Architecture Diagram

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      GAME LOOP (60 FPS)                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  Get Game State  โ”‚
                    โ”‚  [y,v,dx,dy]     โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚  DQN Agent (Inference Mode)   โ”‚
              โ”‚  โ€ข Forward pass through net   โ”‚
              โ”‚  โ€ข Q(s,a) = [Q_nothing,Q_flap]โ”‚
              โ”‚  โ€ข action = argmax(Q-values)  โ”‚
              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  Execute Action  โ”‚
                    โ”‚  Physics update  โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚  Observe: Reward + Next State       โ”‚
        โ”‚  โ€ข Food collision? +10              โ”‚
        โ”‚  โ€ข Food escaped? -2                 โ”‚
        โ”‚  โ€ข New state: [y',v',dx',dy']       โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚ Store Transition in Memory          โ”‚
        โ”‚ (state, action, reward, next_state) โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚  Train on Mini-Batch (when ready)   โ”‚
        โ”‚  โ€ข Sample 64 transitions            โ”‚
        โ”‚  โ€ข Forward pass on current net      โ”‚
        โ”‚  โ€ข Compute target Q with frozen net โ”‚
        โ”‚  โ€ข MSE loss + backprop              โ”‚
        โ”‚  โ€ข Gradient clip + Adam step        โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“ˆ Training Results

Learning Performance

Total Reward per Episode: Reward vs Episode

The agent shows clear learning progression. Early episodes incur heavy exploration penalties (-5000 range), stabilizing as the agent learns efficient strategies.

Food Collection Rate: Score vs Episode

Agent learns to catch 3-5 food items by episode 10 and maintains consistent performance by episode 25, demonstrating stable convergence.


๐ŸŽฏ Engineering Challenges & Solutions

Challenge Root Cause Fix Result
Reward Hacking +0.5 proximity bonus caused hovering Removed proximity bonus, reward only catching Agent actively catches food
Stuck in Local Optima ฮต decay 0.999/ep โ†’ 0.01 in 7 eps Changed to 0.98/ep, maintains 0.10 floor Agent explores all regions
Training Instability No gradient clipping, freq updates Added clip_grad_norm(1.0), 200-step targets Stable convergence
Poor Generalization Always spawn at middle (y=0.5) Random spawn [50px, height-100px] Robust at any position
Distribution Shift Model assumes middle-start position Randomize bird Y during training Handles diverse initial states

Key Engineering Decisions Explained

Reward Shaping Pitfall: Initial +0.5/step bonus for being "close to food" caused reward hackingโ€”agent learned to hover near targets for points without actually catching them. Solution: Only reward terminal actions (food catch +10, food escape -2).

Exploration Decay: Epsilon 0.999/step converged too fast, locking into "stay at top" strategy. Slower decay (0.98/episode) with 0.10 floor maintained 10% exploration throughout training, enabling discovery of diverse strategies.

Gradient Stability: No clipping caused exploding gradients during food-rich episodes. Clip_grad_norm(max_norm=1.0) prevented divergence while maintaining learning speed.


๐Ÿš€ Usage

Quick Start

# 1. Install dependencies
pip install -r requirements.txt

# 2. Play
python main.py

Training Your Own Model

python train.py
# Trains for 50 episodes, saves assets/model/best_model.pth
# Shows live rendering during training (~15 min)
# Edit train.py config for faster headless training

๐ŸŽฎ Game Modes

1. Manual Play

  • Control with SPACEBAR to flap
  • Collect falling food for points
  • Game ends on ground collision
  • Purpose: Understand game mechanics

2. AI Play

  • Watch the trained agent play
  • No user input
  • Shows AI's decision-making in action
  • Purpose: Verify training effectiveness

3. You vs AI

  • Alternating turns: Player then AI
  • Each player tries to catch as much food as possible
  • First to 10 points wins
  • Purpose: Competitive benchmark

๐Ÿ“ Project Structure

Chubby Bird/
โ”œโ”€โ”€ main.py                    # Entry point
โ”œโ”€โ”€ launcher.py                # Game mode router
โ”œโ”€โ”€ train.py                   # DQN training script
โ”œโ”€โ”€ requirements.txt           # Dependencies
โ”œโ”€โ”€ assets/model/best_model.pth             # Trained agent weights
โ”‚
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ settings.py            # Game constants
โ”‚   โ”œโ”€โ”€ agent.py               # DQN model + training logic
โ”‚   โ”œโ”€โ”€ env.py                 # Training environment
โ”‚   โ”œโ”€โ”€ game.py                # Base game loop
โ”‚   โ”œโ”€โ”€ vs_game.py             # Competitive mode
โ”‚   โ”œโ”€โ”€ menu_simple.py         # Menu UI
โ”‚   โ”œโ”€โ”€ bird.py                # Physics + rendering
โ”‚   โ””โ”€โ”€ food.py                # Food spawning
โ”‚
โ””โ”€โ”€ assets/
    โ”œโ”€โ”€ images/                # Sprites & backgrounds
    โ””โ”€โ”€ sounds/                # Audio files

๐Ÿ”ง Quick Reference

Training Configuration

Parameter Value Purpose
Episodes 50 Total training runs
Max steps/episode 3000 Timeout per episode
Learning rate 0.001 Adam optimizer
Discount factor (ฮณ) 0.99 Future reward weight
Epsilon decay 0.98/ep Exploration schedule
Epsilon min 0.10 Min exploration rate
Batch size 64 SGD mini-batch
Memory buffer 5000 Experience replay size
Target update 200 steps Frozen network sync

Game Modes

  • Manual Play: Control with SPACEBAR
  • AI Play: Watch trained agent
  • You vs AI: Competitive mode (first to 10 wins)

๐Ÿ“š What This Demonstrates

โœ… Deep Q-Learning (DQN)
โœ… Experience replay & target networks
โœ… Reward shaping in practice
โœ… Hyperparameter tuning
โœ… Agent evaluation metrics
โœ… Competitive benchmarking


๐Ÿ‘จโ€๐Ÿ’ป Author

Mansoor Bukhari


๐Ÿ“ License

MIT License - Use freely for learning and development.


๐Ÿ™ Acknowledgments

  • Inspired by Flappy Bird and DQN paper (Human-level control through deep RL)
  • Thanks to Pygame community for excellent documentation
  • PyTorch team for intuitive deep learning APIs

About

Chubby Bird is a custom reinforcement learning environment built with Pygame, where a Deep Q-Network agent learns autonomous control to collect food while avoiding penalties.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages