DrawableOrientedSprite

Extends: Sprite

A Sprite that swaps which named animation is active based on the angle between the camera and this entity - the classic Doom/Duke3D "billboard sprite" technique for faking full 3D orientation with pre-rendered 2D views. See docs/drawables-and-scene-objects.md for a full walkthrough and specs/2026-09-22-oriented-sprite-billboards-design.md for the design.

Properties

  • numAngles (integer) — Number of horizontal (azimuth) view buckets around the entity. Bucket 0 is the
  • numElevationBands (integer) — Number of vertical (elevation) view bands, from the camera looking up at the

Constructor

new DrawableOrientedSprite( owner: GameEntity, spriteSheet: ifDraw2d, cellWidth: integer, cellHeight: integer, numAngles?: integer, numElevationBands?: integer, args?: roAssociativeArray, ): DrawableOrientedSprite

Parameters

  • owner (GameEntity)
  • spriteSheet (ifDraw2d)
  • cellWidth (integer)
  • cellHeight (integer)
  • numAngles (integer, optional, default: 8)
  • numElevationBands (integer, optional, default: 1)
  • args (roAssociativeArray, optional, default: "{}")

Instance Methods

addOrientedAnimation( baseName: string, angleFrames: Array.<Array.<integer>>, frameRate: integer, playMode?: SpritePlayMode, ): void

Registers one animation per angle bucket under baseName (e.g. "walk"), for the single elevation band case (the common one - a sheet with no distinct top-down/ bottom-up art). Sugar for addElevationOrientedAnimation with a single-band wrapper; errors (via addElevationOrientedAnimation's own validation) if numElevationBands isn't actually 1.

Parameters

  • baseName (string)
  • angleFrames (Array.<Array.<integer>>) — array of exactly numAngles entries, each an integer[] of frame indexes for that bucket's own art. Every bucket needs its own real art - there is no mirroring/flipping support (see issue #104's design notes for why).
  • frameRate (integer)
  • playMode (SpritePlayMode, optional, default: "SpritePlayMode.Loop")

Returns

  • void

addElevationOrientedAnimation( baseName: string, elevationBands: Array.<Array.<Array.<integer>>>, frameRate: integer, playMode?: SpritePlayMode, ): void

Registers the full elevation x angle grid under baseName. See specs/2026-09-22-oriented-sprite-billboards-design.md for the full bucket-index semantics.

Parameters

  • baseName (string)
  • elevationBands (Array.<Array.<Array.<integer>>>) — array of exactly numElevationBands entries; each entry is itself an angleFrames array in the same shape addOrientedAnimation takes.
  • frameRate (integer)
  • playMode (SpritePlayMode, optional, default: "SpritePlayMode.Loop")

Returns

  • void

registeredAnimationNameForTests( baseName: string, elevationBand: integer, angleBucket: integer, ): string

For tests only - the underlying Sprite animation name a bucket resolves to. Mirrors Sprite's own "for tests only" accessor convention (see rawAnimationClockMsForTests()).

Parameters

  • baseName (string)
  • elevationBand (integer)
  • angleBucket (integer)

Returns

  • string

getOrientedAnimationsDebugInfo(): roAssociativeArray

Debug helper - like Sprite.getAnimationsDebugInfo(), but grouped by baseName and (elevationBand, angleBucket) instead of raw internal Sprite animation names (e.g. "walk_e0_a3") - much easier to check "is the SE bucket for 'walk' really pointing at the sheet region I expect" than wading through synthesized names by hand. See logOrientedAnimationsDebugInfo() to print this as JSON instead of inspecting it directly.

Returns

  • roAssociativeArray

logOrientedAnimationsDebugInfo(): void

Prints getOrientedAnimationsDebugInfo() as JSON via this sprite's owner Game.log().

Returns

  • void

computeAngleBucket( camera: BGE.Camera, toCamera?: BGE.Math.Vector, ): integer

Computes which of numAngles horizontal view buckets is currently visible, from the angle between this entity's facing (rotation.y) and the direction from this entity to the camera. Bucket 0 = the entity's front is facing the camera; buckets increase clockwise as viewed from above. Always 0 for a camera that isn't a Camera3d (a 2D camera has no facing/orbit concept).

Parameters

  • camera (BGE.Camera)
  • toCamera (BGE.Math.Vector, optional, default: "invalid") — the vector from the camera to this entity, if already computed this frame (e.g. by update()) - avoids recomputing it when both this and computeElevationBand() are called for the same camera/frame. Computed internally from camera when omitted.

Returns

  • integer

computeElevationBand( camera: BGE.Camera, toCamera?: BGE.Math.Vector, ): integer

Computes which of numElevationBands vertical view bands is currently visible, from the camera's pitch relative to this entity - band 0 is the camera below the entity looking up at it, band numElevationBands - 1 is the camera above looking down. Always 0 if numElevationBands is 1 (no vertical distinction requested) or the camera isn't a Camera3d.

Parameters

  • camera (BGE.Camera)
  • toCamera (BGE.Math.Vector, optional, default: "invalid") — the vector from the camera to this entity, if already computed this frame (e.g. by update()) - avoids recomputing it when both this and computeAngleBucket() are called for the same camera/frame. Computed internally from camera when omitted.

Returns

  • integer

playOrientedAnimation(baseName: string): void

Selects which base animation is currently playing, analogous to Sprite. playAnimation - but this picks among the (numElevationBands x numAngles) per-bucket animations registered for baseName via addOrientedAnimation / addElevationOrientedAnimation, resolving which one to actually play every update() from the camera's angle to this entity.

Parameters

  • baseName (string)

Returns

  • void

update(): void

Returns

  • void