Skip to content

User Interface

PixelRoot32 provides a complete UI system for creating menus, HUDs, and interface elements. This guide covers all UI components and layout systems.

UI Elements

All UI elements inherit from UIElement, which itself inherits from Entity. This means UI elements can be added to scenes just like any other entity.

UILabel

Display text on screen:

#include <graphics/ui/UILabel.h>

// Create a label
pixelroot32::graphics::ui::UILabel* scoreLabel = new pixelroot32::graphics::ui::UILabel(
    "Score: 0",                    // text
    10,                            // x position
    10,                            // y position
    pixelroot32::graphics::Color::White,  // color
    1                              // size multiplier
);

// Add to scene
addEntity(scoreLabel);

// Update text dynamically
scoreLabel->setText("Score: 100");

// Center horizontally
scoreLabel->centerX(240); // Screen width

UIButton

Create clickable buttons:

#include <graphics/ui/UIButton.h>

// Create a button
pixelroot32::graphics::ui::UIButton* startButton = new pixelroot32::graphics::ui::UIButton(
    "Start Game",                  // text
    4,                             // navigation index
    50,                            // x position
    100,                           // y position
    140,                           // width
    30,                            // height
    []() {                         // callback function
        // Button clicked - start game
        startGame();
    }
);

// Configure style
startButton->setStyle(
    pixelroot32::graphics::Color::White,   // text color
    pixelroot32::graphics::Color::Blue,    // background color
    true                                    // draw background
);

// Add to scene
addEntity(startButton);

UICheckBox

Create interactive checkboxes:

#include <graphics/ui/UICheckBox.h>

// Create a checkbox
pixelroot32::graphics::ui::UICheckBox* soundCheckbox = new pixelroot32::graphics::ui::UICheckBox(
    "Enable Sound",                // text
    4,                             // navigation index
    50,                            // x position
    140,                           // y position
    140,                           // width
    20,                            // height
    true,                          // initial checked state
    [](bool checked) {             // callback function
        // Checkbox state changed
        setSoundEnabled(checked);
    },
    1                              // font size
);

// Configure style
soundCheckbox->setStyle(
    pixelroot32::graphics::Color::White,   // text color
    pixelroot32::graphics::Color::Blue,    // background color
    false                                  // draw background
);

// Add to scene
addEntity(soundCheckbox);

UIPanel

Create visual containers with background and border:

#include <graphics/ui/UIPanel.h>

// Create a panel
pixelroot32::graphics::ui::UIPanel* dialog = new pixelroot32::graphics::ui::UIPanel(
    50,   // x
    50,   // y
    140,  // width
    140   // height
);

// Configure appearance
dialog->setBackgroundColor(pixelroot32::graphics::Color::Black);
dialog->setBorderColor(pixelroot32::graphics::Color::White);
dialog->setBorderWidth(2);

// Add content (typically a layout)
dialog->setChild(menuLayout);

// Add to scene
addEntity(dialog);

Layouts

Layouts automatically organize UI elements, eliminating the need for manual position calculations.

UIVerticalLayout

Organize elements vertically with automatic scrolling:

#include <graphics/ui/UIVerticalLayout.h>

// Create vertical layout
pixelroot32::graphics::ui::UIVerticalLayout* menu = new pixelroot32::graphics::ui::UIVerticalLayout(
    10,   // x
    60,   // y
    220,  // width
    160   // height (viewport)
);

// Configure layout
menu->setPadding(5);        // Internal padding
menu->setSpacing(6);        // Space between elements
menu->setScrollEnabled(true); // Enable scrolling

// Set navigation buttons
menu->setNavigationButtons(0, 1); // UP=0, DOWN=1

// Set button styles
menu->setButtonStyle(
    pixelroot32::graphics::Color::White,  // selected text
    pixelroot32::graphics::Color::Cyan,    // selected background
    pixelroot32::graphics::Color::White,  // unselected text
    pixelroot32::graphics::Color::Black   // unselected background
);

// Add buttons (no manual positioning needed!)
for (int i = 0; i < 10; i++) {
    UIButton* btn = new UIButton(
        "Option " + std::to_string(i),
        i,
        0, 0,  // Position ignored - layout handles it
        200, 20,
        [i]() { handleOption(i); }
    );
    menu->addElement(btn);
}

// Add layout to scene
menu->setRenderLayer(2); // UI layer
addEntity(menu);

UIHorizontalLayout

Organize elements horizontally:

#include <graphics/ui/UIHorizontalLayout.h>

// Create horizontal layout (menu bar)
pixelroot32::graphics::ui::UIHorizontalLayout* menuBar = new pixelroot32::graphics::ui::UIHorizontalLayout(
    0,    // x
    0,    // y
    240,  // width
    30    // height
);

menuBar->setPadding(5);
menuBar->setSpacing(4);
menuBar->setScrollEnabled(true);
menuBar->setNavigationButtons(2, 3); // LEFT=2, RIGHT=3

// Add menu items
menuBar->addElement(new UIButton("File", 0, 0, 0, 60, 20, []() {}));
menuBar->addElement(new UIButton("Edit", 1, 0, 0, 60, 20, []() {}));
menuBar->addElement(new UIButton("View", 2, 0, 0, 60, 20, []() {}));

addEntity(menuBar);

UIGridLayout

Organize elements in a grid (matrix):

#include <graphics/ui/UIGridLayout.h>

// Create grid layout (inventory)
pixelroot32::graphics::ui::UIGridLayout* inventory = new pixelroot32::graphics::ui::UIGridLayout(
    10,   // x
    60,   // y
    220,  // width
    160   // height
);

inventory->setColumns(4);  // 4 columns
inventory->setPadding(5);
inventory->setSpacing(4);
inventory->setNavigationButtons(0, 1, 2, 3); // UP, DOWN, LEFT, RIGHT

// Add items (automatically arranged in grid)
for (int i = 0; i < 16; i++) {
    UIButton* item = new UIButton(
        "Item " + std::to_string(i),
        i,
        0, 0,  // Position ignored
        50, 50,
        [i]() { useItem(i); }
    );
    inventory->addElement(item);
}

addEntity(inventory);

UIAnchorLayout

Position elements at fixed screen positions (perfect for HUDs):

#include <graphics/ui/UIAnchorLayout.h>

// Create anchor layout for HUD
pixelroot32::graphics::ui::UIAnchorLayout* hud = new pixelroot32::graphics::ui::UIAnchorLayout(
    0,    // x
    0,    // y
    240,  // screen width
    240   // screen height
);

hud->setScreenSize(240, 240);

// Add HUD elements at different anchor points
UILabel* scoreLabel = new UILabel("Score: 0", 0, 0, Color::White, 1);
UILabel* livesLabel = new UILabel("Lives: 3", 0, 0, Color::White, 1);

hud->addElement(scoreLabel, pixelroot32::graphics::ui::Anchor::TOP_LEFT);
hud->addElement(livesLabel, pixelroot32::graphics::ui::Anchor::TOP_RIGHT);

addEntity(hud);

Available Anchors: - TOP_LEFT, TOP_RIGHT, TOP_CENTER - BOTTOM_LEFT, BOTTOM_RIGHT, BOTTOM_CENTER - LEFT_CENTER, RIGHT_CENTER - CENTER

UIPaddingContainer

Add padding around a single element:

#include <graphics/ui/UIPaddingContainer.h>

// Create padding container
pixelroot32::graphics::ui::UIPaddingContainer* container = new pixelroot32::graphics::ui::UIPaddingContainer(
    10,   // x
    10,   // y
    200,  // width
    100   // height
);

// Set uniform padding
container->setPadding(10);

// Or set asymmetric padding
container->setPadding(5, 15, 10, 10); // left, right, top, bottom

// Add child element
container->setChild(button);

addEntity(container);

Layouts handle D-pad navigation automatically:

Vertical Navigation

verticalLayout->setNavigationButtons(Buttons::UP, Buttons::DOWN);

// Layout automatically:
// - Highlights selected button
// - Scrolls to keep selected button visible
// - Handles wrapping (optional)

Horizontal Navigation

horizontalLayout->setNavigationButtons(Buttons::LEFT, Buttons::RIGHT);

Grid Navigation

gridLayout->setNavigationButtons(Buttons::UP, Buttons::DOWN, Buttons::LEFT, Buttons::RIGHT);

// Layout automatically:
// - Handles 4-direction navigation
// - Wraps around edges
// - Updates selection

Manual Selection

// Set selected element programmatically
layout->setSelectedIndex(2);

// Get selected element
int selected = layout->getSelectedIndex();
UIElement* element = layout->getSelectedElement();

Complete Example: Main Menu

#include <core/Scene.h>
#include <graphics/ui/UIVerticalLayout.h>
#include <graphics/ui/UIButton.h>
#include <graphics/ui/UILabel.h>
#include <graphics/ui/UIPanel.h>

class MainMenuScene : public pixelroot32::core::Scene {
private:
    pixelroot32::graphics::ui::UIVerticalLayout* menuLayout;
    pixelroot32::graphics::ui::UIPanel* menuPanel;

public:
    void init() override {
        // Create panel
        menuPanel = new pixelroot32::graphics::ui::UIPanel(40, 40, 160, 160);
        menuPanel->setBackgroundColor(pixelroot32::graphics::Color::Black);
        menuPanel->setBorderColor(pixelroot32::graphics::Color::White);
        menuPanel->setBorderWidth(2);
        menuPanel->setRenderLayer(2);
        addEntity(menuPanel);

        // Create layout inside panel
        menuLayout = new pixelroot32::graphics::ui::UIVerticalLayout(0, 0, 160, 160);
        menuLayout->setPadding(10);
        menuLayout->setSpacing(8);
        menuLayout->setNavigationButtons(0, 1);
        menuLayout->setButtonStyle(
            pixelroot32::graphics::Color::White,
            pixelroot32::graphics::Color::Cyan,
            pixelroot32::graphics::Color::White,
            pixelroot32::graphics::Color::Black
        );

        // Add title
        pixelroot32::graphics::ui::UILabel* title = new pixelroot32::graphics::ui::UILabel(
            "GAME MENU", 0, 0, pixelroot32::graphics::Color::Yellow, 2
        );
        menuLayout->addElement(title);

        // Add menu buttons
        menuLayout->addElement(new pixelroot32::graphics::ui::UIButton(
            "Start Game", 0, 0, 0, 140, 25, []() { startGame(); }
        ));

        menuLayout->addElement(new pixelroot32::graphics::ui::UIButton(
            "Options", 1, 0, 0, 140, 25, []() { showOptions(); }
        ));

        menuLayout->addElement(new pixelroot32::graphics::ui::UIButton(
            "Quit", 2, 0, 0, 140, 25, []() { quitGame(); }
        ));

        menuPanel->setChild(menuLayout);
    }

    void update(unsigned long deltaTime) override {
        // Handle input for layout navigation
        auto& input = engine.getInputManager();
        menuLayout->handleInput(input);

        Scene::update(deltaTime);
    }

    void draw(pixelroot32::graphics::Renderer& renderer) override {
        Scene::draw(renderer);
    }
};

Complete Example: HUD

class GameHUD : public pixelroot32::core::Entity {
private:
    pixelroot32::graphics::ui::UIAnchorLayout* hud;
    pixelroot32::graphics::ui::UILabel* scoreLabel;
    pixelroot32::graphics::ui::UILabel* livesLabel;
    pixelroot32::graphics::ui::UILabel* healthLabel;

public:
    GameHUD()
        : Entity(0, 0, 240, 240, pixelroot32::core::EntityType::UI_ELEMENT) {
        setRenderLayer(2); // UI layer

        // Create HUD layout
        hud = new pixelroot32::graphics::ui::UIAnchorLayout(0, 0, 240, 240);
        hud->setScreenSize(240, 240);

        // Create labels
        scoreLabel = new pixelroot32::graphics::ui::UILabel(
            "Score: 0", 0, 0, pixelroot32::graphics::Color::White, 1
        );

        livesLabel = new pixelroot32::graphics::ui::UILabel(
            "Lives: 3", 0, 0, pixelroot32::graphics::Color::White, 1
        );

        healthLabel = new pixelroot32::graphics::ui::UILabel(
            "Health: 100%", 0, 0, pixelroot32::graphics::Color::Green, 1
        );

        // Position labels
        hud->addElement(scoreLabel, pixelroot32::graphics::ui::Anchor::TOP_LEFT);
        hud->addElement(livesLabel, pixelroot32::graphics::ui::Anchor::TOP_RIGHT);
        hud->addElement(healthLabel, pixelroot32::graphics::ui::Anchor::BOTTOM_CENTER);
    }

    void update(unsigned long deltaTime) override {
        // Update HUD text (example)
        char buffer[32];
        snprintf(buffer, sizeof(buffer), "Score: %d", currentScore);
        scoreLabel->setText(buffer);
    }

    void draw(pixelroot32::graphics::Renderer& renderer) override {
        // HUD draws itself through its layout
    }

    // Add HUD to scene
    void addToScene(Scene* scene) {
        scene->addEntity(hud);
    }
};

Best Practices

Organization

  • Use render layer 2: Keep all UI on the top layer
  • Group related elements: Use panels to group menu items
  • Separate HUD from menus: Use different layouts for different UI types
  • Reuse layouts: Create layout factories for common patterns

Performance

  • Layouts use viewport culling: Only visible elements are rendered
  • Minimize text updates: Updating text has overhead
  • Use appropriate layouts: Choose the right layout for your needs
  • Limit element count: Too many elements can impact performance
  • Set navigation buttons: Configure D-pad navigation for layouts
  • Handle input in update(): Check for button presses to trigger actions
  • Provide visual feedback: Selected buttons should be clearly visible
  • Test navigation flow: Ensure navigation feels responsive

Common Patterns

class MenuSystem {
    UIVerticalLayout* currentMenu;

public:
    void showMainMenu() {
        currentMenu = createMainMenu();
        scene->addEntity(currentMenu);
    }

    void showPauseMenu() {
        currentMenu = createPauseMenu();
        scene->addEntity(currentMenu);
    }

    void hideMenu() {
        if (currentMenu) {
            scene->removeEntity(currentMenu);
            currentMenu = nullptr;
        }
    }
};

Dynamic UI Updates

void updateHUD(int score, int lives, int health) {
    char buffer[32];

    snprintf(buffer, sizeof(buffer), "Score: %d", score);
    scoreLabel->setText(buffer);

    snprintf(buffer, sizeof(buffer), "Lives: %d", lives);
    livesLabel->setText(buffer);

    snprintf(buffer, sizeof(buffer), "Health: %d%%", health);
    healthLabel->setText(buffer);
}

Next Steps

Now that you understand the UI system, you've completed the core game development topics. Continue with: - Advanced Graphics - Advanced sprite techniques - Camera and Scrolling - Create scrolling levels - Performance Tuning - Improve performance


See also: - API Reference - UIElement - API Reference - UIButton - API Reference - UI Layouts - Manual - UI Overview