BGE/TileMap

Alias: BGE.TileMap


Static Methods

bakeTileMapImages( tiles: Array.<BGE.TileMap.TileSpec>, chunkSize: float, ): dynamic

static

Bakes a sparse grid of stationary tiles into one or more chunked bitmaps - so a whole screen's worth of static tiles (a platformer level's ground, say) costs one SceneObject/draw call per chunk instead of one per tile. Only chunks that actually contain at least one tile are returned.

Each tile is drawn into its chunk exactly once, at bake time (when this function runs) - not per frame - so this is a one-time cost paid when the level is built, not a recurring one.

chunkSize only controls which tiles get grouped together (tiles are bucketed by Int(worldX / chunkSize), Int(worldY / chunkSize)) - each resulting chunk's bitmap is then sized/anchored to the actual bounding box of the tiles bucketed into it, not to a fixed chunkSize x chunkSize square. This means a tile's footprint is never clipped, even when a visual offset/nudge (e.g. examples/platformer's Level.bs +-5px surface/fill adjustment) pushes it past a grid-aligned bucket boundary - it just makes that one chunk's bitmap a little larger than chunkSize, rather than losing part of the tile.

A screen-aligned Image above ~192px used to silently fail to draw on both the BrightScript Simulator and real hardware, even with fully correct content (confirmed via GetByteArray/tmp:/ PNG round-trip) and a draw call reporting success - traced to Renderer.drawScene() never calling Finish() on its destination before the frame proceeds (see Renderer.bs's own comment on that call, and issue #211). With that fixed, chunkSize up to 512 has been confirmed reliable on real hardware (memory- and disk-sourced images, up to 16 simultaneous 320px blits/frame, sustained). Still keep it well under 768, though: a merged chunk spanning a large mostly-empty vertical gap (e.g. a floating platform merged with unrelated ground tiles far below it) can still silently fail to render at 768+ inside a real running game even though the identical dimensions render reliably in an isolated stress test - see examples/platformer's Level.bs for the specific confirmed-safe/confirmed-broken measurements and the follow-up (issue #213) tracking this remaining gap.

Parameters

  • tiles (Array.<BGE.TileMap.TileSpec>)
  • chunkSize (float) — grouping granularity, in world pixels (keep <= 512)

Returns

  • dynamic

floorDiv(value: float, divisor: float): integer

static

Floor division (not BrightScript's truncate-toward-zero Int()/\) - a tile at a negative world position must bucket into the chunk below/left of the origin, not get pulled back toward chunk 0.

Parameters

  • value (float)
  • divisor (float)

Returns

  • integer

mergeTileColliderRuns( cells: Array.<BGE.TileMap.ColliderCell>, ): dynamic

static

Merges a sparse grid of tagged collision cells into the minimal set of same-tag, contiguous-column runs per row - e.g. a solid platformer floor 20 tiles wide becomes one run instead of 20 separate per-tile colliders. Input order doesn't matter (cells are grouped/sorted internally); a gap in columns or a change in tag always starts a new run. Only merges within a single row - two vertically stacked identical runs are NOT combined into one taller rectangle (that's a further optimization, not implemented here - see bakeTileMapImages() for where the bigger per-frame cost actually lives).

Parameters

  • cells (Array.<BGE.TileMap.ColliderCell>)

Returns

  • dynamic

Other

TileSpec

static

One occupied tile to bake into a chunked tilemap image - addressed by world position (not row/col) since baking is fundamentally about pixels/chunks, not grid adjacency (compare BGE.TileMap.ColliderCell, which stays in grid space).

Properties

  • worldX (float)
  • worldY (float)
  • region (roRegion)
  • width (float)
  • height (float)

BakedChunk

static

One non-empty baked chunk: a single pre-composited bitmap, ready to become one Image drawable (one addImage() call instead of one per tile). worldX/worldY is the chunk's own top-left world corner - worldX the chunk's minimum X, but worldY the chunk's MAXIMUM Y (its top edge, matching TileSpec.worldY's own top-edge convention and Image's top-left-anchor convention, where pixel rows increase downward as world Y decreases) - i.e. where to position the resulting drawable via addImage()'s offset. The bitmap's own width/height are sized to this chunk's actual tile content (see bakeTileMapImages()'s doc comment) - not necessarily the chunkSize passed in.

Properties

  • bitmap (roBitmap)
  • worldX (float)
  • worldY (float)

ColliderCell

static

One occupied collision cell in a tile grid, addressed by integer row/column - merging is pure adjacency in grid space, so world position doesn't come into it at all (unlike bakeTileMapImages(), which bakes pixels and therefore does need world position/chunking).

Properties

  • row (integer)
  • col (integer)
  • tag (string)

MergedColliderRun

static

One merged run of contiguous same-tag cells within a single row.

Properties

  • row (integer)
  • startCol (integer)
  • endCol (integer) — inclusive
  • tag (string) — inclusive