Class: Quake::Game::BrushEntities

Inherits:
Object
  • Object
show all
Defined in:
lib/quake/game/brush_entities.rb

Overview

Manages brush entity behavior: doors, platforms, buttons, triggers. Each entity has a state machine and moves between positions.

Constant Summary collapse

STATE_IDLE =

Entity states

:idle
STATE_OPENING =
:opening
STATE_OPEN =
:open
STATE_CLOSING =
:closing
STATE_CLOSED =
:closed

Instance Method Summary collapse

Constructor Details

#initialize(entities, level, target_map) ⇒ BrushEntities

Returns a new instance of BrushEntities.



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/quake/game/brush_entities.rb', line 15

def initialize(entities, level, target_map)
  @entities = entities
  @level = level
  @target_map = target_map
  @brush_entities = entities.select(&:brush_entity?)

  # Initialize movement data for each brush entity
  @brush_entities.each { |ent| init_brush_entity(ent) }

  puts "Initialized #{@brush_entities.size} brush entities"
end

Instance Method Details

#check_triggers(player_pos, player_radius: 16.0) ⇒ Object

Check if player touches any trigger entities



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/quake/game/brush_entities.rb', line 91

def check_triggers(player_pos, player_radius: 16.0)
  @entities.each do |ent|
    next unless ent.classname.start_with?("trigger_")
    next unless ent.brush_entity?

    model = @level.models[ent.model_index]
    next unless model

    # Simple AABB check against player
    mins = model.mins
    maxs = model.maxs
    origin = ent.position

    if player_pos.x >= origin.x + mins.x - player_radius &&
       player_pos.x <= origin.x + maxs.x + player_radius &&
       player_pos.y >= origin.y + mins.y - player_radius &&
       player_pos.y <= origin.y + maxs.y + player_radius &&
       player_pos.z >= origin.z + mins.z - player_radius &&
       player_pos.z <= origin.z + maxs.z + player_radius
      fire_targets(ent.target) if ent.target
      yield ent if block_given?
    end
  end
end

#platform_motion_for(player_pos) ⇒ Object

Backward-compatible delta-only method



84
85
86
87
88
# File 'lib/quake/game/brush_entities.rb', line 84

def platform_motion_for(player_pos)
  snapped = snap_to_platform(player_pos)
  return Math::Vec3::ORIGIN unless snapped
  snapped - player_pos
end

#snap_to_platform(player_pos) ⇒ Object

If the player is standing on a moving platform, return a new position snapped to the platform’s top surface (so on_ground stays true and the player rides smoothly). Returns nil if not on a moving platform.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/quake/game/brush_entities.rb', line 54

def snap_to_platform(player_pos)
  @brush_entities.each do |ent|
    next unless ent.classname == "func_plat"
    model = @level.models[ent.model_index]
    next unless model

    prev = ent.instance_variable_get(:@prev_pos)
    next unless prev

    ent_delta_z = ent.position.z - prev.z

    # Use the OLD platform position for the on_top check, since
    # player_pos hasn't been updated for this frame's movement yet.
    old_top_z = prev.z + model.maxs.z
    next unless player_pos.z >= old_top_z - 8 && player_pos.z <= old_top_z + 24
    next unless player_pos.x >= ent.position.x + model.mins.x &&
                player_pos.x <= ent.position.x + model.maxs.x &&
                player_pos.y >= ent.position.y + model.mins.y &&
                player_pos.y <= ent.position.y + model.maxs.y

    # Snap to the new platform top surface, slightly above so the
    # trace-down ground check can detect it cleanly (avoid epsilon
    # edge case at exact plane boundary).
    new_top_z = ent.position.z + model.maxs.z + 0.5
    return Math::Vec3.new(player_pos.x, player_pos.y, new_top_z)
  end
  nil
end

#update(dt, player_pos) ⇒ Object

Update all brush entities. Returns entities that need rendering.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/quake/game/brush_entities.rb', line 28

def update(dt, player_pos)
  # Save previous positions for platform-riding
  @brush_entities.each do |ent|
    ent.instance_variable_set(:@prev_pos, ent.position)
  end

  @brush_entities.each do |ent|
    case ent.classname
    when "func_door"
      update_door(ent, dt, player_pos)
    when "func_plat"
      update_platform(ent, dt, player_pos)
    when "func_button"
      update_button(ent, dt, player_pos)
    when "func_train"
      update_train(ent, dt)
    end
  end

  @brush_entities
end