Skip to content

Basic Rendering

Rendering is how you draw everything on screen. This guide covers the fundamental drawing operations in PixelRoot32: primitives, sprites, and text.

Accessing the Renderer

You can access the renderer in two ways:

From the Engine

auto& renderer = engine.getRenderer();

From a Scene

void MyScene::draw(pixelroot32::graphics::Renderer& renderer) override {
    // renderer is passed as parameter
    renderer.drawFilledRectangle(0, 0, 240, 240, Color::Black);
}

Drawing Primitives

Pixels

Draw a single pixel:

renderer.drawPixel(100, 100, pixelroot32::graphics::Color::White);

Lines

Draw a line between two points:

renderer.drawLine(10, 10, 200, 200, pixelroot32::graphics::Color::Red);

Rectangles

Draw a rectangle outline:

renderer.drawRectangle(50, 50, 100, 80, pixelroot32::graphics::Color::Blue);

Draw a filled rectangle:

renderer.drawFilledRectangle(50, 50, 100, 80, pixelroot32::graphics::Color::Blue);

Circles

Draw a circle outline:

renderer.drawCircle(120, 120, 30, pixelroot32::graphics::Color::Green);

Draw a filled circle:

renderer.drawFilledCircle(120, 120, 30, pixelroot32::graphics::Color::Green);

Simple Sprites (1bpp)

Sprites are the primary way to draw game graphics. The standard format is 1bpp (1 bit per pixel), which is memory-efficient and perfect for retro-style graphics.

Creating a Sprite Manually

A 1bpp sprite is defined as an array of uint16_t, where each value represents one row:

#include <graphics/Renderer.h>

// Example: 8x8 sprite (8 rows, each row is a uint16_t)
// Bit 0 = leftmost pixel, bit 7 = rightmost pixel
static const uint16_t MY_SPRITE_DATA[] = {
    0b00111100,  // Row 0:   ..####..
    0b01111110,  // Row 1:  .######.
    0b11111111,  // Row 2:  ########
    0b11111111,  // Row 3:  ########
    0b11111111,  // Row 4:  ########
    0b01111110,  // Row 5:  .######.
    0b00111100,  // Row 6:   ..####..
    0b00000000   // Row 7:  ........
};

// Create sprite descriptor
static const pixelroot32::graphics::Sprite MY_SPRITE = {
    MY_SPRITE_DATA,  // data pointer
    8,                // width
    8                 // height
};

Drawing a Sprite

renderer.drawSprite(
    MY_SPRITE,                                    // sprite
    100,                                          // x position
    100,                                          // y position
    pixelroot32::graphics::Color::White,         // color
    false                                         // flipX (optional, default false)
);

Sprite Bit Convention

  • Each uint16_t represents one row
  • Bit 0 (rightmost bit) = leftmost pixel
  • Bit (width - 1) = rightmost pixel
  • 0 = transparent/off, 1 = on (colored)

Example: For an 8-pixel wide sprite:

Row value: 0b00111100
Pixels:    ..####..
           ^      ^
         bit 7  bit 0 (leftmost)

Flipping Sprites

You can flip a sprite horizontally:

renderer.drawSprite(MY_SPRITE, 100, 100, Color::White, true); // flipped

Text Rendering

PixelRoot32 uses a native bitmap font system for pixel-perfect text rendering.

Drawing Text

renderer.drawText(
    "Hello World!",                           // text string
    10,                                       // x position
    20,                                       // y position
    pixelroot32::graphics::Color::White,     // color
    1                                         // size multiplier (1=normal, 2=double, etc.)
);

Centered Text

renderer.drawTextCentered(
    "Game Over",                              // text
    120,                                      // y position (centered horizontally)
    pixelroot32::graphics::Color::Red,       // color
    2                                         // size
);

Text Size

The size parameter multiplies the font size: - 1 = normal size (5x7 pixels per character with default font) - 2 = double size (10x14 pixels) - 3 = triple size (15x21 pixels) - etc.

Supported Characters

The default font (FONT_5X7) supports ASCII characters 32-126: - Letters: A-Z, a-z - Numbers: 0-9 - Symbols: !@#$%^&*()_+-=[]{}|;:'",.<>?/ etc.

Render Layers

Entities are drawn in order based on their renderLayer property:

  • Layer 0 (Background): Drawn first (behind everything)
  • Layer 1 (Gameplay): Drawn second (main game objects)
  • Layer 2 (UI): Drawn last (on top of everything)

Set the render layer when creating an entity:

myEntity->setRenderLayer(0); // Background
myEntity->setRenderLayer(1); // Gameplay (default)
myEntity->setRenderLayer(2); // UI

Complete Example

Here's a complete example that draws various primitives and a sprite:

#include <core/Scene.h>
#include <graphics/Renderer.h>
#include <graphics/Color.h>

// Simple sprite data (8x8 circle)
static const uint16_t CIRCLE_SPRITE_DATA[] = {
    0b00111100,
    0b01111110,
    0b11111111,
    0b11111111,
    0b11111111,
    0b11111111,
    0b01111110,
    0b00111100
};

static const pixelroot32::graphics::Sprite CIRCLE_SPRITE = {
    CIRCLE_SPRITE_DATA,
    8,
    8
};

class RenderingExampleScene : public pixelroot32::core::Scene {
public:
    void init() override {
        // Set palette
        pixelroot32::graphics::setPalette(
            pixelroot32::graphics::PaletteType::NES
        );
    }

    void update(unsigned long deltaTime) override {
        Scene::update(deltaTime);
    }

    void draw(pixelroot32::graphics::Renderer& renderer) override {
        // Draw background (layer 0)
        renderer.drawFilledRectangle(0, 0, 240, 240, 
            pixelroot32::graphics::Color::Navy);

        // Draw primitives (layer 1)
        renderer.drawRectangle(10, 10, 100, 80, 
            pixelroot32::graphics::Color::White);
        renderer.drawFilledCircle(120, 120, 30, 
            pixelroot32::graphics::Color::Red);
        renderer.drawLine(0, 0, 240, 240, 
            pixelroot32::graphics::Color::Yellow);

        // Draw sprite
        renderer.drawSprite(CIRCLE_SPRITE, 50, 50, 
            pixelroot32::graphics::Color::Cyan);

        // Draw text (layer 2 - UI)
        renderer.drawText("Score: 100", 10, 10, 
            pixelroot32::graphics::Color::White, 1);
        renderer.drawTextCentered("Rendering Demo", 200, 
            pixelroot32::graphics::Color::Yellow, 2);

        Scene::draw(renderer);
    }
};

Best Practices

Performance

  • Minimize draw calls: Batch similar operations when possible
  • Use render layers efficiently: Don't mix layers unnecessarily
  • Avoid drawing off-screen: Check bounds before drawing
  • Reuse sprites: Define sprites once, use many times

Organization

  • Define sprites as static const: Keep them in flash memory
  • Use meaningful names: Name your sprites clearly
  • Group related sprites: Organize sprite data logically
  • Document complex sprites: Comment sprite bit patterns if needed

Text

  • Avoid frequent text updates: Text rendering has overhead
  • Use appropriate sizes: Larger text uses more memory
  • Cache text dimensions: Use FontManager::textWidth() if needed
  • Keep text simple: Complex formatting is not supported

Common Patterns

Drawing a Background

void drawBackground(Renderer& renderer) {
    // Solid color background
    renderer.drawFilledRectangle(0, 0, 240, 240, Color::Black);

    // Or use a tilemap (see Advanced Graphics section)
}

Drawing a HUD

void drawHUD(Renderer& renderer, int score, int lives) {
    char buffer[32];
    snprintf(buffer, sizeof(buffer), "Score: %d", score);
    renderer.drawText(buffer, 10, 10, Color::White, 1);

    snprintf(buffer, sizeof(buffer), "Lives: %d", lives);
    renderer.drawText(buffer, 10, 20, Color::White, 1);
}

Drawing Multiple Sprites

void drawSpriteArray(Renderer& renderer, const Sprite& sprite, 
                     int count, int startX, int startY, int spacing) {
    for (int i = 0; i < count; i++) {
        int x = startX + (i * (sprite.width + spacing));
        renderer.drawSprite(sprite, x, startY, Color::White);
    }
}

Next Steps

Now that you can draw basic graphics, learn about: - Sprites and Animation - Advanced sprite techniques - Input and Control - Make your game interactive - Palettes - Use different color schemes


See also: - API Reference - Renderer - API Reference - Sprite - Render Layers