Skip to content

yunfenglong/Flappy-Birb

Repository files navigation

Flappy Birb

Reactive Flappy Bird clone built entirely with Observables using RxJS. All inputs, time, physics, collisions, state transitions, and rendering are modeled as streams and pure transformations (FRP style).

Overview

  • Framework: Vite + TypeScript + RxJS 7
  • Rendering: SVG
  • Architecture: Pure state reducers scanned over action streams; rendering is derived data; DOM updates are contained to a single subscription
  • Extras: Ghost runs with a simple leaderboard, dynamic pipe score labels, theme toggle, lives with brief invulnerability

Controls

  • Click anywhere: start the game
  • Space: jump
  • R / Enter / Escape: restart after game over
  • Theme toggle button (#themeToggle): switch light/dark

Getting Started

Install

npm install

Run Dev Server

npm run dev

Ctrl-click the URL printed in the terminal to open the app.

Run Tests

npm test       # watch mode
npm run test:ui
npm run test:run  # headless/CI

Build

npm run build

Generate a Pipe Map

Generates a new CSV to assets/map.csv with randomized pipe gaps and times.

npm run generate-pipes

Project Structure

  • src/main.ts: Entrypoint. Wires streams together, fetches the CSV map, starts rendering on first click.
  • src/state.ts: Creates tick$, jump$, restart$ and scans pure reducers into the main State observable.
  • src/physics.ts: Pure physics/jump tick reducers.
  • src/collision.ts: Pure collision detection and status updates.
  • src/rendering.ts: Converts State to render data (SVG element descriptors). DOM writes are centralized elsewhere.
  • src/ghost.ts: Ghost run sampling/visibility and leaderboard computation.
  • src/config.ts: Central config for assets, physics, gameplay, UI selectors, and timings.
  • src/utils.ts: Observable factory helpers (time, keys, combination utilities) and dependency providers.
  • src/types.ts: Shared types, constants, and render/state shapes.
  • src/styles/style.css: Styles including theme classes.
  • index.html: SVG canvas and UI elements (ids must match selectors in config).
  • assets/: birb.png sprite and map.csv level data.
  • tests/main.test.ts: Sample tests using Vitest.

Architecture (FRP with RxJS)

  • Game actions are streams:
    • tick$ emits on an interval
    • jump$ emits on Space key
    • restart$ emits on R/Enter/Escape (only restarts when the run has ended)
  • Actions are pure functions (State) -> State composed via merge and accumulated with scan to produce state$.
  • Rendering derives immutable RenderData from state$ and applies DOM updates in a single subscription, keeping side-effects contained.
  • Pipe layout is loaded from assets/map.csv via fromFetch. The first body click starts the game loop.
  • Ghost positions are sampled and displayed semi-transparently; a small leaderboard tracks top runs.

Configuration

Most knobs live in src/config.ts:

  • Assets: assets/birb.png, assets/map.csv
  • Physics: gravity, jump force, horizontal speed, invulnerability window
  • Gameplay: initial lives, sampling rates, leaderboard size
  • UI: SVG/viewBox, selectors (e.g., #svgCanvas, #gameOver, #themeToggle)
  • Timing: tick rate

Formatting & Tooling

This repo uses Prettier. To format:

npx prettier . --write

The configuration is in .prettierrc.json. If using VS Code, install the Prettier extension and enable format-on-save if desired.

Notes

This project demonstrates FRP style using RxJS and immutable state updates. Keep logic pure and side-effects at the boundaries to align with assessment criteria.

About

Pending distribution to Vercel

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors