DEV Community

Cover image for 🐦 VibeCoding - AmazonQ CLI Building Flappy Bird with Phaser 3 + TypeScript: A Journey from Bugs to Victory
Phạm Tiến Thuận Phát
Phạm Tiến Thuận Phát

Posted on • Edited on

🐦 VibeCoding - AmazonQ CLI Building Flappy Bird with Phaser 3 + TypeScript: A Journey from Bugs to Victory

How I created a fully functional Flappy Bird game and learned valuable lessons about game development, debugging, and problem-solving along the way pair with AmazonQ CLI


🎮 The Challenge

Ever wondered what it takes to recreate one of the most addictive mobile games of all time? I recently embarked on a journey to build Flappy Bird from scratch using modern web technologies, and let me tell you - it was quite an adventure!

Tech Stack:

  • 🎯 Phaser 3 - Game engine
  • 📝 TypeScript - Type safety and better DX
  • 📦 Rollup - Module bundling
  • 🎨 HTML5 Canvas - Rendering
  • 🔊 Web Audio API - Sound effects

Image description

🚀 The Development Journey

Phase 1: Setting Up the Foundation

The project started with a clean architecture approach:

flappy-bird-game/
├── src/
│   ├── scenes/          # Game scenes (Menu, Game, GameOver)
│   ├── objects/         # Game entities (Bird, PipeManager, Background)
│   ├── config/          # Game configuration
│   └── assets/          # Images and sounds
Enter fullscreen mode Exit fullscreen mode

Key decisions:

  • TypeScript for better code maintainability
  • Scene-based architecture for clean separation of concerns
  • Component-based game objects for reusability

Phase 2: The Physics and Animation

Creating the bird was surprisingly fun! Here's what made it special:

export class Bird {
  private sprite: Phaser.Physics.Arcade.Sprite;

  flap(): void {
    this.sprite.setVelocityY(GameConfig.bird.flapStrength); // -350 px/s
    this.flapSound.play();
  }

  update(): void {
    // Realistic rotation based on velocity
    if (this.sprite.body.velocity.y < 0) {
      this.sprite.setRotation(-0.5); // Upward tilt
    } else {
      this.sprite.setRotation(Math.min(0.5, this.sprite.rotation + 0.05));
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The magic details:

  • Smooth rotation that follows physics
  • 🎵 Sound feedback on every flap
  • 🎭 3-frame animation for wing flapping

Phase 3: The Great Scoring System Debugging Saga 🐛

This is where things got really interesting. What seemed like a simple feature turned into a fascinating debugging adventure!

The Problem: Score Wasn't Working! 😱

// ❌ This approach FAILED miserably
this.physics.add.overlap(bird, pipes, (bird, object) => {
    if (object.getData('isScoreTrigger')) {
        score++; // Never executed!
    }
});
Enter fullscreen mode Exit fullscreen mode

The symptoms:

  • Game loaded perfectly ✅
  • Bird physics worked ✅
  • Pipes generated correctly ✅
  • Score remained stubbornly at 0 ❌

Image description

The Investigation 🔍

Through extensive console logging, I discovered:

  1. Overlap detection wasn't firing for invisible score triggers
  2. Mixed object types in physics groups caused conflicts
  3. Phaser's collision system was more complex than expected
// Debug logs revealed the truth:
console.log('Bird position:', birdX, birdY);        // ✅ Working
console.log('Score trigger created:', triggerX);    // ✅ Working  
console.log('Overlap detected:', object);           // ❌ Never appeared!
Enter fullscreen mode Exit fullscreen mode

The Breakthrough: Manual Position Tracking 💡

Instead of fighting with Phaser's physics system, I implemented a custom scoring algorithm:

private checkScoreManually(): void {
    const birdX = 50; // Bird stays at fixed X position

    this.scoreTriggers.forEach(trigger => {
        // Pipes move left: X(t) = X₀ + velocity × deltaTime
        trigger.x += GameConfig.pipes.speed * deltaTime; // -200 px/s

        // Score when pipe passes bird (left movement)
        if (!trigger.scored && trigger.x <= birdX && trigger.x > birdX - 50) {
            trigger.scored = true;
            this.passedPipes++;
            this.scene.events.emit('score-updated', this.passedPipes);
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

The key insight: In Flappy Bird, the bird doesn't move horizontally - the pipes move toward the bird! 🤯

🎯 Technical Highlights

1. Smart Asset Management

// Automated asset copying during build
const copyAssets = () => {
    copyDir('./src/assets', './dist/src/assets');
    console.log('Assets copied successfully!');
};
Enter fullscreen mode Exit fullscreen mode

2. Persistent High Score System

// Simple but effective localStorage implementation
const highScore = localStorage.getItem('flappyHighScore') || 0;
if (currentScore > highScore) {
    localStorage.setItem('flappyHighScore', String(currentScore));
    showNewRecordAnimation(); // ✨ Visual feedback
}
Enter fullscreen mode Exit fullscreen mode

3. Performance Optimizations

  • Object pooling for pipes
  • Manual cleanup of off-screen objects
  • Efficient collision detection only where needed
  • Optimized sprite animations

🏆 The Final Result

After solving the scoring system puzzle, everything clicked into place:

Game Features:

  • Smooth 60fps gameplay
  • Accurate collision detection
  • Persistent high scores
  • Sound effects and animations
  • Responsive controls (mouse + keyboard)
  • Mobile-friendly design

🎓 Lessons Learned

1. Sometimes Simple Solutions Win

Complex framework features aren't always the answer. My manual position tracking turned out to be more reliable than Phaser's built-in collision system.

2. Debug Logging is Your Best Friend

console.log('🎯 Manual score detection! Pipe passed bird at X:', triggerX);
console.log('✅ New score:', this.passedPipes);
Enter fullscreen mode Exit fullscreen mode

Those emoji-filled logs made debugging actually enjoyable!

3. Understanding Game Mechanics Matters

I initially misunderstood how Flappy Bird works. The bird doesn't move horizontally - this insight was crucial for fixing the scoring system.

4. TypeScript + Game Development = ❤️

Type safety caught numerous bugs before runtime and made refactoring much safer.

🔧 The Architecture That Worked

graph TB
    A[GameScene] --> B[Bird]
    A --> C[PipeManager]  
    A --> D[Background]
    C --> E[Manual Score Detection]
    B --> F[Physics & Animation]
    A --> G[Collision System]
    H[GameConfig] --> A
Enter fullscreen mode Exit fullscreen mode

Detailed Class Diagram

Key Components:

  • GameScene: Orchestrates everything
  • Bird: Physics-based player character
  • PipeManager: Obstacle generation + custom scoring
  • Background: Scrolling environment
  • GameConfig: Centralized configuration

🚀 Try It Yourself!

Want to build your own version? Here's the quick start:

# Clone and setup
git clone <your-repo>
cd flappy-bird-game
npm install

# Build and run
npm run build
npm run serve

# Open http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Pro tips for aspiring game developers:

  1. Start with a simple game loop
  2. Add one feature at a time
  3. Debug with extensive logging
  4. Don't be afraid to try different approaches
  5. Test frequently on different devices

🎮 What's Next?

The game is fully playable, but there's always room for improvement:

  • 📱 Mobile touch controls
  • 🎨 Particle effects for enhanced visuals
  • 🏆 Online leaderboards
  • 🎵 Background music
  • 🔧 Level editor

💭 Final Thoughts

Building Flappy Bird taught me that game development is as much about problem-solving as it is about coding. The scoring system bug that initially frustrated me became the most educational part of the entire project.

The real victory wasn't just creating a working game - it was learning to debug systematically, think creatively about solutions, and persist through challenging problems.

Whether you're a seasoned developer or just starting out, I encourage you to try building a simple game. You'll be surprised by how much you learn about programming, problem-solving, and the satisfaction of creating something interactive and fun!


🔗 Resources & Links


What's your experience with game development? Have you faced similar debugging challenges? Share your stories in the comments below! 👇

Happy coding, and may your birds always flap smoothly! 🐦✨


Tags: #AmazonQCLI #gamedev #typescript #phaser #javascript #webdev #debugging #flappybird #html5games

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.