Skip to main content

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

UseAvoid 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

PhaseBehavior
BuildCreates one compositor sprite for each decor item, initially hidden and parked offscreen.
World updateHs2dWorld.update calls each group with the active camera and viewport size.
Group updateComputes x = worldX - camera.x * parallaxX and y = worldY - camera.y * parallaxY, applies culling padding, toggles drawable, and moves changed sprites.
Render/composeThe 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 cullPaddingX and cullPaddingY to avoid popping without keeping distant sprites visible.
  • Use decor for visuals only. Entities with collisions or state should be built through entities bindings and Hs2dSpriteGroup.
  • Keep frame assets on the Hs2dAssetGate so 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

SourceWhy it matters
../games/hosanna-ui/src/hosanna-game/scene/GameSceneRenderer.tsParallaxSpriteGroup, ParallaxSpriteLayer, item options, culling, movement, and host compositor behavior.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorld.tsaddParallaxSprites, group registration, and per-frame group updates.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorldBuilder.tsTiled hs2d:role=decor, frame resolution, culling properties, and z defaults.
../hosanna-ui-game-samples-public/src/hosanna-game-examples/native-shoot-em-up/VerticalShooterLevelScene.tsExample decorFrames mapping for map-driven space decoration.
Talk to us