Class: RGame::Core::TileMapRenderer
- Inherits:
-
Object
- Object
- RGame::Core::TileMapRenderer
- Defined in:
- lib/rgame/core/tile_map_renderer.rb
Overview
Draws a tile map: the static layers baked once, the animated tiles drawn per frame and culled to the viewport.
tiles = RGame::Core::TileMapRenderer.new(map, tileset_images)
tiles.draw(renderer, camera_x, camera_y, view_w, view_h, elapsed: seconds)
tiles.(renderer, camera_x, camera_y, view_w, view_h, z: 20,
elapsed: seconds)
Two bands, with the actors between them
Layers split by the map's own above_layer? flag. The below band —
ground, and detail on the actors' level — is drawn under them by #draw;
the above band — tree canopies, roofs — over them by #draw_overlay,
at a z the scene picks. Two calls rather than one because the scene
draws its actors in between, and collapsing them would put every canopy
behind every character.
What is baked and what is not
Within each band, every tile that is not animated is baked into one recording, the first time that band is drawn. Scrolling a baked layer is then one call per texture however many thousand tiles went into it. The handful that are animated are drawn individually each frame, culled to the viewport — a map far larger than the screen costs only what is on it.
It loads nothing and holds no clock
The tiles arrive already sliced, so two maps sharing a tileset share one GPU upload — which is only true if something above pulled the image through the asset manager, and is why this class does not load its own.
And elapsed is an argument rather than a clock read, so animation is
something the caller advances. Pausing is "stop accumulating"; a spec
picks the frame it wants. See CLAUDE.md, "draw renders state; time
enters through update".
What it needs of a map
It never names the map's class — the tile map lives a layer above this
one and Core may not reach up (CLAUDE.md, "The rule points both ways").
What it calls is the 'a tile map' contract in
spec/support/shared_examples/: layer_count, above_layer?, width,
height, tile_width, tile_height, gid, and a tileset answering
local_id, animations and frame_local_id.
Constant Summary collapse
- BELOW_Z =
The ground band sits at the bottom; the scene chooses where the overlay goes, because only it knows what its actors are drawn at.
0
Instance Attribute Summary collapse
-
#map ⇒ Object
readonly
The map this was built from.
Instance Method Summary collapse
- #draw(renderer, camera_x, camera_y, viewport_width, viewport_height, elapsed: 0.0) ⇒ Object
- #draw_overlay(renderer, camera_x, camera_y, viewport_width, viewport_height, z:, elapsed: 0.0) ⇒ Object
-
#initialize(map, tiles) ⇒ TileMapRenderer
constructor
tilesis the tileset image sliced into an Array indexed by local tile id — whatImage#tilesreturns.
Constructor Details
#initialize(map, tiles) ⇒ TileMapRenderer
tiles is the tileset image sliced into an Array indexed by local tile
id — what Image#tiles returns.
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/rgame/core/tile_map_renderer.rb', line 57 def initialize(map, tiles) @map = map @tileset = map.tileset @tiles = tiles @animated_below, @animated_above = collect_animated_tiles # Baked on first draw, not here: recording needs a live frame, and there # is no renderer at construction. @static_below = nil @static_above = nil end |
Instance Attribute Details
#map ⇒ Object (readonly)
The map this was built from. A scene reads it for collision and world bounds, which are its business rather than this class's.
53 54 55 |
# File 'lib/rgame/core/tile_map_renderer.rb', line 53 def map @map end |
Instance Method Details
#draw(renderer, camera_x, camera_y, viewport_width, viewport_height, elapsed: 0.0) ⇒ Object
68 69 70 71 72 73 |
# File 'lib/rgame/core/tile_map_renderer.rb', line 68 def draw(renderer, camera_x, camera_y, , , elapsed: 0.0) @static_below ||= bake(renderer) { |layer| !@map.above_layer?(layer) } @static_below.draw(-camera_x, -camera_y, z: BELOW_Z) draw_animated(renderer, @animated_below, camera_x, camera_y, , , BELOW_Z, elapsed) end |
#draw_overlay(renderer, camera_x, camera_y, viewport_width, viewport_height, z:, elapsed: 0.0) ⇒ Object
75 76 77 78 79 80 81 |
# File 'lib/rgame/core/tile_map_renderer.rb', line 75 def (renderer, camera_x, camera_y, , , z:, elapsed: 0.0) @static_above ||= bake(renderer) { |layer| @map.above_layer?(layer) } @static_above.draw(-camera_x, -camera_y, z: z) draw_animated(renderer, @animated_above, camera_x, camera_y, , , z, elapsed) end |