Class: RGame::Engine::TileCollision

Inherits:
Object
  • Object
show all
Defined in:
lib/rgame/engine/tile_collision.rb

Overview

Axis-separated AABB-vs-tile collision resolution (pure). solid is a callable solid.call(col, row) -> bool. Resolve X then Y (with the X result) to get wall-sliding. Assumes per-step movement smaller than a tile (no tunneling), which holds for our speeds.

Constant Summary collapse

EPS =
1e-9

Instance Method Summary collapse

Constructor Details

#initialize(tile_width:, tile_height:, solid:) ⇒ TileCollision

Returns a new instance of TileCollision.



12
13
14
15
16
# File 'lib/rgame/engine/tile_collision.rb', line 12

def initialize(tile_width:, tile_height:, solid:)
  @tile_width = tile_width
  @tile_height = tile_height
  @solid = solid
end

Instance Method Details

#resolve_x(x, y, w, h, dx) ⇒ Object

Move an AABB (top-left x, y; size w, h) by dx, snapping flush against solids.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rgame/engine/tile_collision.rb', line 19

def resolve_x(x, y, w, h, dx)
  nx = x + dx
  return nx if dx.zero?

  first_row = (y / @tile_height).floor
  last_row  = ((y + h - EPS) / @tile_height).floor

  if dx.positive?
    col = ((nx + w - EPS) / @tile_width).floor
    return col * @tile_width - w if solid_in_rows?(col, first_row, last_row)
  else
    col = (nx / @tile_width).floor
    return (col + 1) * @tile_width if solid_in_rows?(col, first_row, last_row)
  end
  nx
end

#resolve_y(x, y, w, h, dy) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rgame/engine/tile_collision.rb', line 36

def resolve_y(x, y, w, h, dy)
  ny = y + dy
  return ny if dy.zero?

  first_col = (x / @tile_width).floor
  last_col  = ((x + w - EPS) / @tile_width).floor

  if dy.positive?
    row = ((ny + h - EPS) / @tile_height).floor
    return row * @tile_height - h if solid_in_cols?(row, first_col, last_col)
  else
    row = (ny / @tile_height).floor
    return (row + 1) * @tile_height if solid_in_cols?(row, first_col, last_col)
  end
  ny
end