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¶
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:
Lines¶
Draw a line between two points:
Rectangles¶
Draw a rectangle outline:
Draw a filled rectangle:
Circles¶
Draw a circle outline:
Draw a filled circle:
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_trepresents 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:
Flipping Sprites¶
You can flip a sprite horizontally:
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