Flappy Bird Example
Demonstration project — provided as an example of what the PixelRoot32 Game Engine can do. It is not a product: parts may be incomplete, experimental, or deliberately simplified to keep one idea in focus.
Language: C++17
Engine: gperez88/PixelRoot32-Game-Engine@^1.9.0
Environments: native, esp32c3
Category: Games
A Flappy Bird–style game: bird is a RigidActor (gravity + flap impulse), pipes are KinematicActor pairs that scroll and recycle when off-screen. Score and game states (waiting / playing / game over) are handled in FlappyBirdScene, which drives them through the engine's gameplay::StateMachine.
Requirements (build flags)
PIXELROOT32_ENABLE_PHYSICS=1— required onesp32c3inplatformio.ini.PIXELROOT32_ENABLE_GAMEPLAY_STATE_MACHINE=1— required on every environment. The scene'sWAITING/RUNNING/GAME_OVERmachine is agameplay::StateMachinemember, and the whole class lives behind this flag (default0), so the scene does not compile without it.PIXELROOT32_ENABLE_PROFILING— enabled on theesp32c3environment in this project (optional for learning builds).- U8g2 path (hardware):
PIXELROOT32_USE_U8G2,PIXELROOT32_NO_TFT_ESPIonesp32c3.
The logical framebuffer is 72×40 pixels, centered in a 128×64 physical OLED via X_OFF_SET, Y_OFF_SET, LOGICAL_WIDTH, LOGICAL_HEIGHT in platformio.ini.
Platforms
| Environment | Target |
|---|---|
native | SDL2 window sized for the same logical resolution (offsets in platformio.ini) |
esp32c3 | DFRobot Beetle ESP32-C3 (board = dfrobot_beetle_esp32c3) with U8g2 display (no TFT_eSPI on this preset) |
This example does not ship an esp32dev TFT environment — only native + esp32c3.
Controls
- Action / Jump — button 0 (
FlappyBirdConstants/ scene input) to flap when running. - Avoid pipes and the top/bottom bounds; pass gaps to increase score.
Features
Physics actors for bird and pipes
Object pool–style pipe reuse
Small-resolution rendering path suited for 128×64 OLED via U8g2
gameplay::StateMachinefor theWAITING→RUNNING→GAME_OVERcycle, with the per-state entry work inonEntercallbacks: enteringWAITINGresets bird, pipes and score; enteringRUNNINGfires the first flap and reveals the pipes.GAME_OVERhas no entry side effect — its text is drawn per frame from the current state.Transitions are requested directly from
update()rather than from anonUpdatecallback. This is deliberate: the frame that leavesWAITINGmust still run the pipe-scroll and scoring block, andStateMachine::update()does not cascadeonUpdateinto a newly entered state within the same call. See the comment at the call site inFlappyBirdScene.cpp.
Documentation links
- Physics API
- Core API
- Platform / drivers
- Memory system — gameplay flags and byte budgets — RAM cost of
PIXELROOT32_ENABLE_GAMEPLAY_STATE_MACHINE gameplay/StateMachine.h— the full contract, including the time-in-state ordering warning onupdate()
Build
From examples/flappy_bird:
pio run -e native
pio run -e esp32c3Upload (ESP32-C3)
pio run -e esp32c3 --target uploadWire your OLED according to the U8g2 configuration used in this project’s platform header / driver setup.
Source code: https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Demo-Projects/tree/main/games/flappy_bird
