Module: Doom::Game::Geometry
- Defined in:
- lib/doom/game/geometry.rb
Overview
Shared 2D geometry for the simulation. These three helpers were copy-pasted across combat, monster AI, player physics, world and sector actions (the last under the name point_line_dist); consolidated here so line-of-sight, collision and use-line checks share one definition.
Pure functions of their arguments -- no state, no RNG, no wall clock -- so they stay deterministic and every peer computes the same result.
Class Method Summary collapse
-
.line_circle_intersect?(x1, y1, x2, y2, cx, cy, radius) ⇒ Boolean
Does the segment (x1,y1)->(x2,y2) pass within
radiusof the circle centred at (cx,cy)? The collision test for a body of that radius sliding against a wall. -
.point_to_segment_distance(px, py, x1, y1, x2, y2) ⇒ Object
Shortest distance from point (px,py) to the segment (x1,y1)->(x2,y2), clamped to the segment ends.
-
.segments_intersect?(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) ⇒ Boolean
Do the open segments A (ax1,ay1)->(ax2,ay2) and B (bx1,by1)->(bx2,by2) cross? Used for line-of-sight and hitscan against walls.
Class Method Details
.line_circle_intersect?(x1, y1, x2, y2, cx, cy, radius) ⇒ Boolean
Does the segment (x1,y1)->(x2,y2) pass within radius of the circle
centred at (cx,cy)? The collision test for a body of that radius sliding
against a wall.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/doom/game/geometry.rb', line 36 def line_circle_intersect?(x1, y1, x2, y2, cx, cy, radius) dx = cx - x1 dy = cy - y1 line_dx = x2 - x1 line_dy = y2 - y1 line_len_sq = (line_dx * line_dx) + (line_dy * line_dy) return false if line_len_sq.zero? t = (((dx * line_dx) + (dy * line_dy)).to_f / line_len_sq).clamp(0.0, 1.0) closest_x = x1 + (t * line_dx) closest_y = y1 + (t * line_dy) dist_sq = ((cx - closest_x)**2) + ((cy - closest_y)**2) dist_sq < radius * radius end |
.point_to_segment_distance(px, py, x1, y1, x2, y2) ⇒ Object
Shortest distance from point (px,py) to the segment (x1,y1)->(x2,y2), clamped to the segment ends. Used for use-line and trigger proximity.
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/doom/game/geometry.rb', line 53 def point_to_segment_distance(px, py, x1, y1, x2, y2) dx = px - x1 dy = py - y1 line_dx = x2 - x1 line_dy = y2 - y1 line_len_sq = (line_dx * line_dx) + (line_dy * line_dy) return Math.sqrt((dx * dx) + (dy * dy)) if line_len_sq.zero? t = (((dx * line_dx) + (dy * line_dy)).to_f / line_len_sq).clamp(0.0, 1.0) closest_x = x1 + (t * line_dx) closest_y = y1 + (t * line_dy) Math.sqrt(((px - closest_x)**2) + ((py - closest_y)**2)) end |
.segments_intersect?(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) ⇒ Boolean
Do the open segments A (ax1,ay1)->(ax2,ay2) and B (bx1,by1)->(bx2,by2) cross? Used for line-of-sight and hitscan against walls. Parallel or barely-crossing segments (tiny determinant) count as no intersection.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/doom/game/geometry.rb', line 18 def segments_intersect?(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) d1x = ax2 - ax1 d1y = ay2 - ay1 d2x = bx2 - bx1 d2y = by2 - by1 denom = (d1x * d2y) - (d1y * d2x) return false if denom.abs < 0.001 dx = bx1 - ax1 dy = by1 - ay1 t = ((dx * d2y) - (dy * d2x)).to_f / denom u = ((dx * d1y) - (dy * d1x)).to_f / denom t > 0.0 && t < 1.0 && u >= 0.0 && u <= 1.0 end |