Class: RGame::Engine::Components::TileWorld

Inherits:
RGame::Engine::Component show all
Defined in:
lib/rgame/engine/components/tile_world.rb

Overview

The scene-scoped tile world: a system component (it lives on the scene node and is found with node.system(TileWorld)) that owns the parsed Engine::TileMap and everything an actor needs from it — collision against the solid tiles, the world bounds, and drawing the map through the scene's camera.

Collision reuses Engine::CollisionSystem (TileCollision + a world-bounds clamp); the tile solidity is whatever the map's tileset reports (baked per-tile in Tiled).

It does not draw. Drawing the map is RGame::Engine::TileMapLayer, one node per Tiled layer, mounted inside the WorldView so the map is drawn once per viewport like the rest of the world. This stays a system — the thing actors ask about collision and bounds — and a system that also drew was always the odd part of it.

It owns the map's animation clock. Nothing below reads a wall clock — see CLAUDE.md, "draw renders state; time enters through update" — so the elapsed seconds animated tiles run on are accumulated here and handed down at draw time. Stop calling update and the water freezes, which is what pausing should look like.

Instance Attribute Summary collapse

Attributes inherited from RGame::Engine::Component

#node

Instance Method Summary collapse

Methods inherited from RGame::Engine::Component

#context, #control, #draw, #on_attach, #on_detach, #sweep_freed

Methods included from Signal::DSL

#signal

Constructor Details

#initialize(map:, tilemap_id:, cameras: []) ⇒ TileWorld

cameras are the cameras this map bounds — every player's, normally. A camera may not show past the world's edges, and this is what knows how big the world is; the cameras themselves are owned by players.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rgame/engine/components/tile_world.rb', line 31

def initialize(map:, tilemap_id:, cameras: [])
  super()
  @map = map
  @tilemap_id = tilemap_id
  @elapsed = 0.0
  Array(cameras).each { |camera| bound(camera) }
  @collision = Engine::CollisionSystem.new(
    tile_collision: Engine::TileCollision.new(
      tile_width: map.tile_width, tile_height: map.tile_height,
      solid: ->(col, row) { map.solid_tile?(col, row) }
    ),
    world_width: map.pixel_width, world_height: map.pixel_height
  )
end

Instance Attribute Details

#elapsedObject (readonly)

Returns the value of attribute elapsed.



26
27
28
# File 'lib/rgame/engine/components/tile_world.rb', line 26

def elapsed
  @elapsed
end

#tilemap_idObject (readonly)

Returns the value of attribute tilemap_id.



26
27
28
# File 'lib/rgame/engine/components/tile_world.rb', line 26

def tilemap_id
  @tilemap_id
end

Instance Method Details

#bound(camera) ⇒ Object

Clamp a camera to this map's edges. Called for each camera the scene hands over, and again for one that arrives later (a player joining).



62
63
64
65
66
# File 'lib/rgame/engine/components/tile_world.rb', line 62

def bound(camera)
  camera.world_width = @map.pixel_width
  camera.world_height = @map.pixel_height
  camera
end

#first_above_layerObject

The first layer Tiled flags above, or the layer count if none is — which is where TileMapLayer.mount leaves the gap for the actors, so a map with no flag puts them over everything. Read once at mount rather than per frame: which layers cover the actors is a fact about the scene's arrangement, and the arrangement is made once.



56
57
58
# File 'lib/rgame/engine/components/tile_world.rb', line 56

def first_above_layer
  layer_count.times.find { |index| @map.above_layer?(index) } || layer_count
end

#layer_countObject



49
# File 'lib/rgame/engine/components/tile_world.rb', line 49

def layer_count = @map.layer_count

#move(actor, dx, dy) ⇒ Object

Move an actor (responds to x/y/collision_box) by (dx, dy), sliding along solids and clamped inside the world. Delegates to the reused collision system.



70
# File 'lib/rgame/engine/components/tile_world.rb', line 70

def move(actor, dx, dy) = @collision.move(actor, dx, dy)

#solid?(col, row) ⇒ Boolean

Returns:

  • (Boolean)


72
# File 'lib/rgame/engine/components/tile_world.rb', line 72

def solid?(col, row) = @map.solid_tile?(col, row)

#update(dt) ⇒ Object

Advances the tile animations. Seconds, like every other duration here.



75
76
77
# File 'lib/rgame/engine/components/tile_world.rb', line 75

def update(dt)
  @elapsed += dt
end

#world_heightObject



47
# File 'lib/rgame/engine/components/tile_world.rb', line 47

def world_height = @map.pixel_height

#world_widthObject



46
# File 'lib/rgame/engine/components/tile_world.rb', line 46

def world_width = @map.pixel_width