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:
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:
Keep game rules in update hooks. Keep rendering code as state projection into existing layers.
Layer Types
| Page | Primary use |
|---|---|
| Sky | Screen-fit static background and clear-color visual base. |
| Direct parallax | Surface-less scrolling strip for final background art. |
| Surface parallax | Cached compositor surface for parallax art that needs repeat, zoom constraints, or surface composition. |
| Parallax sprite groups | Map-placed decorative sprites with parallax factors and culling. |
| Sprite | Pooled actors, projectiles, pickups, and bound map entities. |
| Direct sprite | Retained, surface-less sprite groups for a modest number of visible actors. |
| Dynamic tile | Either a visible-window compositor-sprite pool or a ring surface for scrolling terrain. |
| Static tile | One cached whole-map surface for small static maps. |
| Cached chunk tile | Tight cached chunk surfaces for large static tile maps. |
| Particle | Fixed particle sprite pool hosted by a sprite layer compositor. |
| HUD | Screen-space final overlay callback and cached text helper. |
| Cached surface | Custom world surface painted once and viewport-blitted. |
| Custom | Last-resort per-frame compose callback. |
Construction Patterns
Prefer the highest-level construction path that matches the content source:
| Content source | Construction path |
|---|---|
| Tiled map image, tile, decor, and entity layers | Hs2dWorldBuilder.fromLevel(...). |
| Hand-built game world | Hs2dWorld.create(...) plus addSky, addHs2dSpriteLayer, addTileLayer, and related methods. |
| Standalone renderer diagnostics | GameSceneRenderer plus explicit layer instances. |
| Expensive static custom art | world.addCachedSurfaceLayer(...). |
| Legacy or temporary special case | world.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:
| Desired per-frame work | Use |
|---|---|
| One screen background blit | Sky. |
| One or two clipped strip blits | Direct parallax. |
| Move a compositor sprite, redraw a small surface only when dirty | Surface parallax. |
| Retarget visible tile sprites as the camera moves | Dynamic tile. |
| Crop and scale one prepainted map surface | Static tile or cached surface. |
| Draw only visible prepainted chunk surfaces | Cached chunk tile. |
| Move and hide pooled sprites | Sprite layer, sprite pools, sprite groups, particle layer. |
| Project and directly blit a modest number of retained actors | Direct sprite layer. |
| Repaint only tile rows and columns entering a scrolling window | Dynamic ring-surface tile layer. |
| Draw final screen-space HUD | HUD 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
| Source | Why it matters |
|---|---|
../games/hosanna-ui/src/hosanna-game/scene/GameSceneRenderer.ts | Base layer interface, surface layers, sky, parallax, sprite layers, HUD, and render-frame order. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorld.ts | Public world API for adding layers, ticking cameras, updating pools, rendering, snapshots, and disposal. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/game/Hs2dLevelScene.ts | Scene-level update template for logic, sprite sync, particles, stats, loading, and render. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorldBuilder.ts | Tiled-to-world build path and layer-mode selection. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dRingTileLayer.ts | Retained tile ring, entering-row/column repaint, crop composition, and stats. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dDirectSpriteLayer.ts | Retained surface-less groups, culling, projection, and direct composition. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dNativeSpriteBatch.ts | Optional native compositor batch and failure fallback contract. |
docs/hosanna-game/performance-covenant.md | Project-level performance rules that all layer work should follow. |