API Reference
📖 API Reference
Complete reference of all engine classes and functions.
Game Interface (src/core/game.h)
class Game {
public:
virtual ~Game() = default;
// Name of the game (for the menu/launcher)
virtual const char* name() const = 0;
// Called once when the game starts
virtual void init() = 0;
// Called every frame (~60 FPS)
// @param in Current input state
// @param dtMs Time since the last frame in milliseconds
virtual void update(const InputState& in, uint32_t dtMs) = 0;
// Draws the game to gfx.tft()
virtual void draw() = 0;
// Optional: cleanup before switching games
virtual void quit() {}
// Set to true to return to the launcher
bool wantsMenu = false;
};
Engine (src/core/engine.h)
class Engine {
public:
// Starts the given game (nullptr = show the menu)
void begin(Game* game);
// Main loop - call from Arduino loop()
void loop();
};
extern Engine engine; // Global instance
Usage in main.cpp:
#include "core/engine.h"
#include "games/games.h"
void setup() {
engine.begin(nullptr); // nullptr = launcher menu
// engine.begin(makeGame(2)); // boot directly into a game (for testing)
}
void loop() {
engine.loop();
}
The engine runs a launcher menu when no game is active: A/B short = select, B long = start the selected game.
Input (src/core/input.h)
Key Enum
enum class Key : uint8_t { A, B, KeyCount };
// Key::A = 0, Key::B = 1
InputState
struct InputState {
bool down[2]; // true while the button is held
bool pressed[2]; // true only in the frame of the release (short)
bool longPressed[2]; // true once after a long hold
uint32_t holdMs[2]; // hold time in ms (0 = not pressed)
};
InputManager
class InputManager {
public:
void init(); // call once
void update(InputState& s); // call every frame
};
extern InputManager input; // Global instance
ButtonTracker (src/core/buttons.h)
enum class BtnEvent : uint8_t {
None, // No event
Short, // Short press (released before longMs)
Long // Long press (longMs reached)
};
class ButtonTracker {
public:
ButtonTracker(uint8_t pin, uint32_t longMs, uint32_t debounceMs = 30);
BtnEvent update(); // call every frame
bool isDown() const; // true while held
uint32_t heldMs() const; // hold time in ms
};
Display (src/core/display.h)
class Display {
public:
void init(); // initialize the display
TFT_eSPI& tft(); // access the TFT_eSPI object
static constexpr int16_t width(); // display width (170)
static constexpr int16_t height(); // display height (320)
};
extern Display gfx; // Global instance
Example:
#include "core/display.h"
auto& tft = gfx.tft();
tft.fillScreen(TFT_BLACK);
tft.drawString("Hello", 10, 10, 2);
Board Configuration (src/boards/board_*.h)
All boards define these constants in the board namespace:
namespace board {
// Button pins
constexpr uint8_t PIN_BTN_A; // Button A (e.g. BOOT)
constexpr uint8_t PIN_BTN_B; // Button B
constexpr uint8_t PIN_POWER_ON; // Power-hold (must be HIGH)
constexpr bool HAS_POWER_HOLD; // true if a power-hold pin exists
// Timing
constexpr uint32_t LONG_A_MS; // ms until Long for A
constexpr uint32_t LONG_B_MS; // ms until Long for B
constexpr uint32_t DEBOUNCE_MS; // debounce time
// Display
constexpr uint8_t TFT_ROTATION; // 0-3
constexpr int16_t SCR_W; // width in sketch orientation
constexpr int16_t SCR_H; // height in sketch orientation
}
Game Registry (src/games/games.h)
// Create a game
Game* makeGame(uint8_t index);
// Number of registered games
constexpr uint8_t GAME_COUNT;
There is no BOOT_GAME constant. To boot directly into a game
(skipping the menu), call engine.begin(makeGame(N)) in main.cpp.
SpriteRenderer (src/games/neonrun/sprites.h)
For swappable graphics themes:
struct NeonPalette {
uint16_t bgTop, bgMid, bgBottom; // background
uint16_t star, horizon; // decoration
uint16_t player, playerGlow; // player
uint16_t obstacle, obstacleDark; // obstacles
uint16_t coin, coinDark; // collectibles
uint16_t text, textDim; // text
};
class SpriteRenderer {
public:
virtual const NeonPalette& palette() const = 0;
virtual void drawBackground(TFT_eSprite& fb, uint32_t scroll) = 0;
virtual void drawPlayer(TFT_eSprite& fb, int16_t x, int16_t y, bool visible) = 0;
virtual void drawBarObstacle(TFT_eSprite& fb, int16_t x, int16_t y,
int16_t w, int16_t h,
int16_t gapX, int16_t gapW) = 0;
virtual void drawDrone(TFT_eSprite& fb, int16_t x, int16_t y, uint32_t t) = 0;
virtual void drawCoin(TFT_eSprite& fb, int16_t x, int16_t y, uint32_t t) = 0;
};
extern SpriteRenderer* gSprites; // active theme
extern NeonVectorTheme neonVectorTheme; // default theme
TFT_eSPI Reference (Excerpt)
Colors (RGB565)
| Constant | Value | Color |
|---|---|---|
TFT_BLACK |
0x0000 | black |
TFT_WHITE |
0xFFFF | white |
TFT_RED |
0xF800 | red |
TFT_GREEN |
0x07E0 | green |
TFT_BLUE |
0x001F | blue |
TFT_YELLOW |
0xFFE0 | yellow |
TFT_MAGENTA |
0xF81F | magenta |
TFT_CYAN |
0x07FF | cyan |
TFT_ORANGE |
0xFD20 | orange |
TFT_GRAY / TFT_DARKGRAY |
0x7BEF / 0x39E7 | grey |
TFT_LIGHTGRAY |
0xC618 | light grey |
Text Datums (Alignment)
tft.setTextDatum(TL_DATUM); // Top-Left (default)
tft.setTextDatum(TC_DATUM); // Top-Center
tft.setTextDatum(TR_DATUM); // Top-Right
tft.setTextDatum(ML_DATUM); // Middle-Left
tft.setTextDatum(MC_DATUM); // Middle-Center
tft.setTextDatum(MR_DATUM); // Middle-Right
tft.setTextDatum(BL_DATUM); // Bottom-Left
tft.setTextDatum(BC_DATUM); // Bottom-Center
tft.setTextDatum(BR_DATUM); // Bottom-Right
Important Methods
TFT_eSPI tft;
// Init
tft.init();
tft.setRotation(0); // 0-3
// Screen
tft.fillScreen(color);
// Text
tft.setTextColor(fg, bg);
tft.setTextDatum(datum);
tft.drawString(str, x, y, font); // font: 1-8
tft.drawNumber(num, x, y, font);
tft.drawFloat(num, decimals, x, y, font);
// Shapes
tft.drawPixel(x, y, color);
tft.drawLine(x1, y1, x2, y2, color);
tft.drawRect(x, y, w, h, color);
tft.fillRect(x, y, w, h, color);
tft.drawRoundRect(x, y, w, h, r, color);
tft.fillRoundRect(x, y, w, h, r, color);
tft.drawCircle(cx, cy, r, color);
tft.fillCircle(cx, cy, r, color);
tft.drawTriangle(x1,y1, x2,y2, x3,y3, color);
tft.fillTriangle(x1,y1, x2,y2, x3,y3, color);
// Bitmaps
tft.pushImage(x, y, w, h, data); // RGB565
tft.pushImage(x, y, w, h, data, transparent);
tft.drawBitmap(x, y, data, w, h, fg, bg); // 1-bit
// Measurement
tft.textWidth(str, font);
tft.fontHeight(font);
TFT_eSprite (Framebuffer)
TFT_eSprite spr{&tft};
spr.setColorDepth(16); // 8 or 16 bit
spr.createSprite(w, h); // allocate memory
spr.deleteSprite(); // free
// Same drawing methods as TFT_eSPI
spr.fillSprite(color);
spr.drawString(...);
// ...
spr.pushSprite(x, y); // output to display
spr.pushSprite(x, y, transparent);
Arduino/ESP32 Functions
Time
millis(); // ms since boot (uint32_t, wraps after ~49 days)
micros(); // µs since boot
delay(ms); // blocks (avoid in the game loop!)
delayMicroseconds(us);
Random
randomSeed(seed); // set by the engine (esp_random())
random(max); // 0 to max-1
random(min, max); // min to max-1
Memory
ESP.getFreeHeap(); // free heap (internal RAM)
ESP.getFreePsram(); // free PSRAM
ESP.getHeapSize(); // total heap
ESP.getPsramSize(); // total PSRAM
GPIO
pinMode(pin, OUTPUT);
pinMode(pin, INPUT);
pinMode(pin, INPUT_PULLUP);
digitalWrite(pin, HIGH/LOW);
digitalRead(pin);
Constants Reference
Display (T-Display-S3)
| Constant | Value |
|---|---|
gfx.width() |
170 (portrait) |
gfx.height() |
320 (portrait) |
board::TFT_ROTATION |
0 (portrait) |
Timing
| Constant | Value | Meaning |
|---|---|---|
board::LONG_A_MS |
1200 ms | long press for button A |
board::LONG_B_MS |
700 ms | long press for button B |
board::DEBOUNCE_MS |
30 ms | debounce time |
Engine::FRAME_MS |
16 ms | ~60 FPS target frame rate |
Pins (T-Display-S3)
| Constant | GPIO | Function |
|---|---|---|
board::PIN_BTN_A |
0 | BOOT button |
board::PIN_BTN_B |
14 | second button |
board::PIN_POWER_ON |
15 | power-hold (HIGH) |