Parallax Sprite Groups
Parallax sprite groups are for map-placed decorative sprites that move at parallax rates. They are not gameplay actors. A ParallaxSpriteGroup creates compositor sprites on an existing sprite layer, tracks each item's world position and parallax factors, and toggles drawability based on camera visibility.
Use groups for decorative moons, stations, rocks, decals, signs, and other fixed world objects. Gameplay actors should use Hs2dSpriteLayer sprite groups or sprite pools instead.
When To Use
| Use | Avoid when |
|---|---|
| Static decorative objects from Tiled object layers. | Objects need health, AI, collision ownership, or gameplay state. |
| Per-object parallax values and culling. | The art can be baked into a cached surface or chunked tile layer. |
| Dozens or low hundreds of fixed decor sprites. | Thousands of objects would create too many compositor sprites. |
Construction Pattern
The builder path is normally preferred. In Tiled:
Object layer: decals
hs2d:role = decor
hs2d:z = 30
Object properties:
frame = moon
parallaxX = 0.15
parallaxY = 0.25
zIndex = 32
cullPaddingX = 512
cullPaddingY = 512
In code, register any decor frame aliases on the builder:
const built = Hs2dWorldBuilder.fromLevel({
level,
assets,
viewportWidth: screenWidth,
viewportHeight: screenHeight,
spriteLayerId: 'foreground',
decorFrames: {
moon: 'space-moon',
station: 'space-station',
},
});
Manual worlds can call world.addParallaxSprites after creating a host sprite layer.
Update, Render, And Compose Behavior
| Phase | Behavior |
|---|---|
| Build | Creates one compositor sprite for each decor item, initially hidden and parked offscreen. |
| World update | Hs2dWorld.update calls each group with the active camera and viewport size. |
| Group update | Computes x = worldX - camera.x * parallaxX and y = worldY - camera.y * parallaxY, applies culling padding, toggles drawable, and moves changed sprites. |
| Render/compose | The host SpriteLayer renders and composes its compositor surface. The group itself is not a renderer layer. |
Because groups write into a sprite layer compositor, their render order is controlled by the host layer order and per-sprite z values.
Performance Notes
- Parallax sprite groups allocate one physical sprite per item. Keep decor counts bounded.
- Prefer cached surfaces for dense static decoration.
- Use
cullPaddingXandcullPaddingYto avoid popping without keeping distant sprites visible. - Use decor for visuals only. Entities with collisions or state should be built through
entitiesbindings andHs2dSpriteGroup. - Keep frame assets on the
Hs2dAssetGateso missing decor fails at build time.
Code Sample
const foreground = world.addHs2dSpriteLayer({
id: 'foreground',
width: screenWidth,
height: screenHeight,
offscreenX: -1000,
offscreenY: -1000,
});
world.addParallaxSprites({
id: 'space-decals',
layer: foreground,
offscreenX: -1000,
offscreenY: -1000,
items: [
{
source: moonRegion,
worldX: 420,
worldY: 180,
parallaxX: 0.12,
parallaxY: 0.2,
zIndex: 10,
cullPaddingX: 640,
cullPaddingY: 420,
},
],
});
Source References
| Source | Why it matters |
|---|---|
../games/hosanna-ui/src/hosanna-game/scene/GameSceneRenderer.ts | ParallaxSpriteGroup, ParallaxSpriteLayer, item options, culling, movement, and host compositor behavior. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorld.ts | addParallaxSprites, group registration, and per-frame group updates. |
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorldBuilder.ts | Tiled hs2d:role=decor, frame resolution, culling properties, and z defaults. |
../hosanna-ui-game-samples-public/src/hosanna-game-examples/native-shoot-em-up/VerticalShooterLevelScene.ts | Example decorFrames mapping for map-driven space decoration. |