Sprite Renderer
SpriteRenderer is the component that makes a GameObject visible on screen. It is split into two parts - a Sprite asset that holds pixel data in flash, and the SpriteRenderer component that submits draw commands to the renderer. Most project sprites now come from the asset pipeline as generated Assets::NAME constants in GeneratedAssets/WE_Assets.hpp, but the manual API is the same either way.
Step 1 â Define Pixel Data
Create a constexpr uint8_t array in flash. This can live anywhere â inline in your class, in a dedicated sprites header, or in generated code from the asset pipeline.
Valid sizes: rectangular [H][W] arrays with W and H each in the range 1..96. Non-2D arrays or out-of-range dimensions are compile errors.
constexpr uint8_t playerPixels[3][3] = {
{0, 1, 0},
{1, 2, 1},
{0, 1, 0}
};
â Define pixel arrays as
constexprso they live in flash, not RAM.
Step 2 â Create a Sprite Asset
Sprite is a plain data asset â not a component. Use Sprite::Create() to turn your pixel array into a Sprite, or include the generated asset header and use the Assets namespace when the converter has already done that work for you.
constexpr Sprite SPRITE_PLAYER = Sprite::Create(playerPixels, PALETTE_WARM);
Step 3 â Attach a SpriteRenderer
Declare a SpriteRenderer as a public member of your GameObject using the constructor below:
SpriteRenderer(owner, sprite, layer)
| Parameter | Type | Description |
|---|---|---|
owner |
GameObject* |
The owning object â always pass this |
sprite |
const Sprite* |
Pointer to a constexpr Sprite asset in flash (pixels + palette + anchor) |
layer |
RenderLayer |
Render layer â defaults to RenderLayer::Default if omitted |
#include "WolfEngine/ComponentSystem/Components/WE_Comp_SpriteRenderer.hpp"
#include "WolfEngine/Graphics/ColorPalettes/WE_Palettes.hpp"
class Player : public GameObject {
public:
SpriteRenderer spriteRenderer = SpriteRenderer(this, &SPRITE_PLAYER, RenderLayer::Player);
};
SpriteRenderer is tick-enabled by default. During component tick it:
- Converts world position to screen position using the camera
- Culls sprites fully outside the game region
- Submits a sprite
DrawCommandto the renderer
This happens only when Settings.render.spriteSystemEnabled is true.
Because command submission happens in component tick (before Update() and camera follow), sprites render using previous-frame transform/camera state.
Note: You can use your defined render layers with the RenderLayer enum. Check Layers for more information.
Pixel Data Format
Pixel arrays are row-major, left to right, top to bottom. Each byte is a palette index (0â31). Index 0 is always transparent.
// 0 = transparent, 1 = outline, 2 = fill, 3 = highlight
constexpr uint8_t coinPixels[8][9] = {
// 0 0 1 1 1 1 0 0 0
{ 0,0,1,1,1,1,0,0,0 },
// 0 1 2 3 3 2 1 0 0
{ 0,1,2,3,3,2,1,0,0 },
// 0 1 3 2 2 3 1 0 0
{ 0,1,3,2,2,3,1,0,0 },
// 0 1 2 3 3 2 1 0 0
{ 0,1,2,3,3,2,1,0,0 },
// 0 1 3 2 2 3 1 0 0
{ 0,1,3,2,2,3,1,0,0 },
// 0 1 2 3 3 2 1 0 0
{ 0,1,2,3,3,2,1,0,0 },
// 0 1 2 2 2 2 1 0 0
{ 0,1,2,2,2,2,1,0,0 },
// 0 0 1 1 1 1 0 0 0
{ 0,0,1,1,1,1,0,0,0 },
};
constexpr Sprite SPRITE_COIN = Sprite::Create(coinPixels, PALETTE_WARM);
Keeping a comment map above each row makes sprite data human readable and easy to edit.
Palette Variants
SpriteRenderer no longer owns a separate palette pointer. To change appearance, create sprite variants that share the same pixels and use setSprite().
constexpr uint8_t enemyPixels[8][8] = { /* ... */ };
constexpr Sprite ENEMY_NORMAL = Sprite::Create(enemyPixels, PALETTE_WARM);
constexpr Sprite ENEMY_HIT = Sprite::Create(enemyPixels, PALETTE_SUNSET);
spriteRenderer.setSprite(&ENEMY_NORMAL);
spriteRenderer.setSprite(&ENEMY_HIT);
See Settings for related render settings and configuration context.
Rotation
Sprites support four snap rotations applied per-pixel at draw time:
spriteRenderer.setRotation(Rotation::R0); // default â no rotation
spriteRenderer.setRotation(Rotation::R90); // 90° clockwise
spriteRenderer.setRotation(Rotation::R180); // 180°
spriteRenderer.setRotation(Rotation::R270); // 270° clockwise
Anchors are stored in Sprite (anchorX, anchorY). By default they are centered (W/2, H/2) and remain pinned to the GameObject position across all rotations.
Visibility
Hide a sprite without destroying the GameObject:
spriteRenderer.setVisible(false); // hidden â skipped by renderer each frame
spriteRenderer.setVisible(true); // visible again
Sort Key Override
By default, sprites are ordered within the same render layer by draw Y. You can override this with setSortKey():
spriteRenderer.setSortKey(100); // explicit order inside the same layer
spriteRenderer.clearSortKey(); // back to default drawY sorting
Swapping Sprites
Swap the active Sprite asset at runtime with setSprite(). This is how the Animator drives frame-based animation - just a pointer swap, no allocation and no manual render-pipeline changes.
spriteRenderer.setSprite(&SPRITE_WALK_A);
spriteRenderer.setSprite(&SPRITE_WALK_B);
Note: Never reassign a
SpriteRenderermember with= SpriteRenderer(...)at runtime. Update sprite/rotation/visibility on the existing component instance instead.
Animation
For frame-based animation use the Animator component â it handles frame timing and calls setSprite() automatically. See Animator for details.
Getters
spriteRenderer.getSprite(); // const Sprite*
spriteRenderer.isVisible(); // bool
spriteRenderer.getRotation(); // Rotation
spriteRenderer.getLayer(); // int