Skip to main content

Layers Overview

An Hs2d world is a camera plus ordered layers. Layers own the expensive renderer resources: compositor surfaces, compositor sprites, tile pools, chunk surfaces, cached world surfaces, particle sprite pools, and HUD callbacks. Gameplay code updates logical state, then syncs that state into layers and pools.

Use Hs2d layers, pools, and cached surfaces for gameplay rendering. Raw screen.DrawObject, screen.DrawScaledObject, screen.DrawRect, and screen.DrawText loops are reserved for bounded diagnostics, loading screens, or carefully measured custom layers.

Frame Contract

GameSceneRenderer.renderFrame(screen) uses the same shape for every renderer layer:

GameSceneRenderer preparing retained layers, rendering their resources, conditionally clearing the target, and composing in insertion orderGameSceneRenderer preparing retained layers, rendering their resources, conditionally clearing the target, and composing in insertion order

Hs2dWorld.tick and Hs2dWorld.update synchronize non-renderer tile/group state before render and prepare every renderer layer by default. Hs2dLevelScene.tickSceneCamera() uses updateSpriteLayers: false, so renderer preparation waits until render after the scene has synchronized logical sprites. Direct GameSceneRenderer users may rely on lazy preparation in renderFrame(). If the camera changes after preparation, the renderer prepares again. Hs2dLevelScene follows a fixed frame template:

Accepted Hs2d gameplay frame showing logical update, retained-state synchronization, world rendering, and telemetry gatesAccepted Hs2d gameplay frame showing logical update, retained-state synchronization, world rendering, and telemetry gates

Keep game rules in update hooks. Keep rendering code as state projection into existing layers.

Layer Types

PagePrimary use
SkyScreen-fit static background and clear-color visual base.
Direct parallaxSurface-less scrolling strip for final background art.
Surface parallaxCached compositor surface for parallax art that needs repeat, zoom constraints, or surface composition.
Parallax sprite groupsMap-placed decorative sprites with parallax factors and culling.
SpritePooled actors, projectiles, pickups, and bound map entities.
Direct spriteRetained, surface-less sprite groups for a modest number of visible actors.
Dynamic tileEither a visible-window compositor-sprite pool or a ring surface for scrolling terrain.
Static tileOne cached whole-map surface for small static maps.
Cached chunk tileTight cached chunk surfaces for large static tile maps.
ParticleFixed particle sprite pool hosted by a sprite layer compositor.
HUDScreen-space final overlay callback and cached text helper.
Cached surfaceCustom world surface painted once and viewport-blitted.
CustomLast-resort per-frame compose callback.

Construction Patterns

Prefer the highest-level construction path that matches the content source:

Content sourceConstruction path
Tiled map image, tile, decor, and entity layersHs2dWorldBuilder.fromLevel(...).
Hand-built game worldHs2dWorld.create(...) plus addSky, addHs2dSpriteLayer, addTileLayer, and related methods.
Standalone renderer diagnosticsGameSceneRenderer plus explicit layer instances.
Expensive static custom artworld.addCachedSurfaceLayer(...).
Legacy or temporary special caseworld.addCustomLayer(...), with the performance covenant applied manually.

Layer file order in a prepared Tiled level becomes render order. Manual worlds add layers in the order the add* methods are called.

Choosing A Layer

Choose the layer by the runtime work you want per frame:

Tile-renderer selection matrix distinguishing builder auto, dynamic sprite pools, manual ring surfaces, static whole-map surfaces, and cached chunksTile-renderer selection matrix distinguishing builder auto, dynamic sprite pools, manual ring surfaces, static whole-map surfaces, and cached chunks

Desired per-frame workUse
One screen background blitSky.
One or two clipped strip blitsDirect parallax.
Move a compositor sprite, redraw a small surface only when dirtySurface parallax.
Retarget visible tile sprites as the camera movesDynamic tile.
Crop and scale one prepainted map surfaceStatic tile or cached surface.
Draw only visible prepainted chunk surfacesCached chunk tile.
Move and hide pooled spritesSprite layer, sprite pools, sprite groups, particle layer.
Project and directly blit a modest number of retained actorsDirect sprite layer.
Repaint only tile rows and columns entering a scrolling windowDynamic ring-surface tile layer.
Draw final screen-space HUDHUD layer.

Specialized Retained Paths

Hs2dDirectSpriteLayer sits between raw immediate drawing and a compositor-surface sprite layer. Each group owns stable logical slots, performs camera culling and projection in update(), then draws visible cached regions directly in z order. Hosanna Dungeon uses it for pickups, projectiles, enemies, partners, and heroes.

Hs2dNativeSpriteBatch is a lower-level compositor helper rather than a world layer. Call queue() for visible integer positions, then flush() once at the intended z point. On Roku, the flush moves, changes, hides, and draws pooled compositor sprites inside one native block. It disables itself after allocation or draw failure so a caller can fall back. No current sample uses this standalone helper directly. Vertical Shooter instead uses the separate Hs2dSpritePool.flushNativeBatch(...) path for selected pools; see Sprite Layer.

Code Sample

const world = Hs2dWorld.create({
x: 0,
y: 0,
viewportWidth: screenWidth,
viewportHeight: screenHeight,
worldWidth: level.worldWidth,
worldHeight: level.worldHeight,
clearColor: 0x000000ff,
});

world.addSky({ source: skyBitmap, clearColor: 0x000000ff });

const foreground = world.addHs2dSpriteLayer({
id: 'foreground',
width: screenWidth,
height: screenHeight,
cullPadding: 128,
offscreenX: -1000,
offscreenY: -1000,
});

world.addTileLayer({
id: 'terrain',
mode: 'dynamic',
layer: foreground,
tileWidth: 32,
tileHeight: 32,
worldColumns: level.width,
worldRows: level.height,
tileKinds,
regions: tileRegions,
minScale: 0.8,
});

world.addHud(this);

Source References

SourceWhy it matters
../games/hosanna-ui/src/hosanna-game/scene/GameSceneRenderer.tsBase layer interface, surface layers, sky, parallax, sprite layers, HUD, and render-frame order.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorld.tsPublic world API for adding layers, ticking cameras, updating pools, rendering, snapshots, and disposal.
../games/hosanna-ui/src/hosanna-game/hosanna2d/game/Hs2dLevelScene.tsScene-level update template for logic, sprite sync, particles, stats, loading, and render.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorldBuilder.tsTiled-to-world build path and layer-mode selection.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dRingTileLayer.tsRetained tile ring, entering-row/column repaint, crop composition, and stats.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dDirectSpriteLayer.tsRetained surface-less groups, culling, projection, and direct composition.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dNativeSpriteBatch.tsOptional native compositor batch and failure fallback contract.
docs/hosanna-game/performance-covenant.mdProject-level performance rules that all layer work should follow.
Talk to us