Class: Quake::Game::Engine
- Inherits:
-
Object
- Object
- Quake::Game::Engine
- Defined in:
- lib/quake/game/engine.rb
Overview
Encapsulates the entire game state and per-frame loop, allowing both interactive (bin/quake) and scripted (bin/quake-debug) execution.
Defined Under Namespace
Classes: DynamicLight, Projectile, TemporaryBeam, TemporaryBeamSegment, TemporaryDynamicLight, WeaponSound
Constant Summary collapse
- POWERUP_EXPIRING_EVENTS =
{ ring: :ring_expiring, pentagram: :pentagram_expiring, biosuit: :biosuit_expiring, quad: :quad_expiring }.freeze
- POWERUP_EXPIRING_MESSAGES =
CheckPowerups sprints (client.qc) shown when a powerup has less than three seconds left.
{ ring: "Ring of Shadows magic is fading", pentagram: "Protection is almost burned out", biosuit: "Air supply in Biosuit expiring", quad: "Quad Damage is wearing off" }.freeze
- CENTERPRINT_TIME =
scr_centertime (screen.c) and con_notifytime (console.c) defaults.
2.0- CON_NOTIFYTIME =
3.0- MAX_NOTIFY_LINES =
NUM_CON_TIMES notify lines shown at once (console.c Con_DrawNotify).
4- START_ITEM_CLASSNAMES =
%w[ item_health item_armor1 item_armor2 item_armorInv weapon_supershotgun weapon_nailgun weapon_supernailgun weapon_grenadelauncher weapon_rocketlauncher weapon_lightning item_shells item_spikes item_rockets item_cells item_weapon item_key1 item_key2 item_sigil item_artifact_invulnerability item_artifact_envirosuit item_artifact_invisibility item_artifact_super_damage ].freeze
- ITEM_WIDE_BOUNDS_CLASSNAMES =
%w[ item_health item_shells item_spikes item_rockets item_cells item_weapon ].freeze
- ITEM_TALL_BOUNDS_CLASSNAMES =
%w[ item_armor1 item_armor2 item_armorInv weapon_supershotgun weapon_nailgun weapon_supernailgun weapon_grenadelauncher weapon_rocketlauncher weapon_lightning ].freeze
- QUAKEWORLD_REMOVED_MONSTER_CLASSNAMES =
%w[ monster_ogre monster_demon1 monster_shambler monster_knight monster_army monster_wizard monster_dog monster_zombie monster_boss monster_tarbaby monster_hell_knight monster_fish monster_shalrath monster_enforcer monster_oldone ].freeze
- PLAYER_DEATH_FRAMES =
{ axe: (41..49).to_a, a: (50..60).to_a, b: (61..69).to_a, c: (70..84).to_a, d: (85..93).to_a, e: (94..102).to_a }.freeze
- PLAYER_DEATHA11_FRAME =
60- PLAYER_PAIN_FRAMES =
{ axe: (29..34).to_a, normal: (35..40).to_a }.freeze
- PLAYER_STAND_FRAMES =
{ axe: (17..28).to_a, normal: (12..16).to_a }.freeze
Instance Attribute Summary collapse
-
#attack_pressed ⇒ Object
writeonly
Sets the attribute attack_pressed.
-
#axe ⇒ Object
Returns the value of attribute axe.
-
#brush_game ⇒ Object
readonly
Returns the value of attribute brush_game.
-
#camera ⇒ Object
readonly
Returns the value of attribute camera.
-
#deathmatch ⇒ Object
Returns the value of attribute deathmatch.
-
#dynamic_lights ⇒ Object
readonly
Returns the value of attribute dynamic_lights.
-
#entities ⇒ Object
readonly
Returns the value of attribute entities.
-
#fraglimit ⇒ Object
Returns the value of attribute fraglimit.
-
#game_time ⇒ Object
Returns the value of attribute game_time.
-
#hud ⇒ Object
readonly
Returns the value of attribute hud.
-
#item_pickups ⇒ Object
readonly
Returns the value of attribute item_pickups.
-
#level ⇒ Object
readonly
Returns the value of attribute level.
-
#pak ⇒ Object
readonly
Returns the value of attribute pak.
-
#palette ⇒ Object
readonly
Returns the value of attribute palette.
-
#particles ⇒ Object
readonly
Returns the value of attribute particles.
-
#player ⇒ Object
readonly
Returns the value of attribute player.
-
#player_state ⇒ Object
readonly
Returns the value of attribute player_state.
-
#rj ⇒ Object
Returns the value of attribute rj.
-
#samelevel ⇒ Object
Returns the value of attribute samelevel.
-
#sound_events ⇒ Object
readonly
Returns the value of attribute sound_events.
-
#teamplay ⇒ Object
Returns the value of attribute teamplay.
-
#temp1 ⇒ Object
Returns the value of attribute temp1.
-
#timelimit ⇒ Object
Returns the value of attribute timelimit.
-
#viewmodel ⇒ Object
readonly
Returns the value of attribute viewmodel.
-
#wad ⇒ Object
readonly
Returns the value of attribute wad.
-
#window ⇒ Object
readonly
Returns the value of attribute window.
Instance Method Summary collapse
- #active_centerprint ⇒ Object
- #active_notify_lines ⇒ Object
-
#adjust_viewsize(delta) ⇒ Object
viewsize like Quake's +/- keys: 120 hides the bar, 110 shows the status bar only (default), 100 adds the inventory bar.
- #clear_keys ⇒ Object
- #dump_state ⇒ Object
-
#hud_stats ⇒ Object
Level statistics for the HUD (Quake's cl.stats STAT_MONSTERS / STAT_SECRETS etc. plus intermission state, sbar.c).
-
#initialize(pak_path:, window: nil, window_visible: true, window_width: nil, window_height: nil, enable_sound: true, enable_render: true, registered: false) ⇒ Engine
constructor
A new instance of Engine.
- #keys ⇒ Object
-
#load_map(map_name) ⇒ Object
Load a BSP map and (re)build all per-level state.
- #render ⇒ Object
- #sb_lines ⇒ Object
-
#screenshot(filename) ⇒ Object
---------------------- debug output -----------------------.
- #set_attack(pressed) ⇒ Object
-
#set_key(scancode, pressed) ⇒ Object
---------------------- input control ----------------------.
- #set_keys(keys_hash) ⇒ Object
- #shutdown ⇒ Object
-
#sprint(text) ⇒ Object
QuakeC sprint(): queue a console notify line (top-left text, console.c Con_Print + Con_DrawNotify).
- #swap_buffers ⇒ Object
-
#teleport(x, y, z, yaw: nil, pitch: nil) ⇒ Object
---------------------- player control ---------------------.
-
#tick(dt) ⇒ Object
Update + render one frame.
-
#update_screen_messages ⇒ Object
Latch centerprints written to the player (QuakeC centerprint()) and drop expired on-screen text.
Constructor Details
#initialize(pak_path:, window: nil, window_visible: true, window_width: nil, window_height: nil, enable_sound: true, enable_render: true, registered: false) ⇒ Engine
Returns a new instance of Engine.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/quake/game/engine.rb', line 90 def initialize(pak_path:, window: nil, window_visible: true, window_width: nil, window_height: nil, enable_sound: true, enable_render: true, registered: false) @enable_render = enable_render @registered = registered # PAK + assets @pak = Pak::Reader.new(pak_path) @palette = Palette.new(@pak.read("gfx/palette.lmp")) wad_data = @pak.read("gfx.wad") @wad = Wad::Reader.new(wad_data) if wad_data # Sound (optional) if enable_sound @sound_mixer = Sound::Mixer.new(@pak) @sound_mixer.open end @sound_events = Sound::Events.new(@sound_mixer) # Window if window @window = window @owns_window = false else opts = { visible: window_visible } opts[:width] = window_width if window_width opts[:height] = window_height if window_height @window = Window.new(**opts) @owns_window = true end @keys = {} @attack_pressed = false @attack_finished = 0.0 @pending_changelevel = nil @pending_changelevel_time = nil @samelevel = 0 @deathmatch = 0 @teamplay = 0 @rj = 1.0 @axe = 0 @temp1 = 0 @timelimit = 0 @fraglimit = 0 @current_map = nil @killed_monsters = 0 @total_monsters = 0 @level_name = nil @intermission_running = false @intermission_start_time = nil @gravity = GRAVITY @projectiles = [] @temporary_dynamic_lights = [] @temporary_beams = [] @environment_damage_time = 0.0 @air_finished = 12.0 @drown_damage = 2.0 @drown_pain_finished = 0.0 @pain_sound_finished = 0.0 @invincible_sound_finished = 0.0 @swim_sound_finished = 0.0 @quad_attack_sound_finished = 0.0 @ring_idle_sound_finished = 0.0 @powerup_warning_finished = {} @bonus_cshift_percent = 0.0 @damage_cshift = Renderer::GLViewBlend::CShift.new(color: [0, 0, 0], percent: 0.0) @damage_kick_time = 0.0 @damage_kick_roll = 0.0 @damage_kick_pitch = 0.0 @weapon_punch_angle = Math::Vec3::ORIGIN @view_oldz = 0.0 @view_frame_dt = 0.0 @view_idle_scale = 0.0 @view_idealpitch = 0.0 @view_pitch_velocity = 0.0 @view_pitch_nodrift = true @view_pitch_driftmove = 0.0 @view_pitch_laststop = 0.0 @jump_flag = 0.0 @game_time = 0.0 @notify_lines = [] @centerprint = nil @centerprint_expire = nil end |
Instance Attribute Details
#attack_pressed=(value) ⇒ Object (writeonly)
Sets the attribute attack_pressed
88 89 90 |
# File 'lib/quake/game/engine.rb', line 88 def attack_pressed=(value) @attack_pressed = value end |
#axe ⇒ Object
Returns the value of attribute axe.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def axe @axe end |
#brush_game ⇒ Object (readonly)
Returns the value of attribute brush_game.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def brush_game @brush_game end |
#camera ⇒ Object (readonly)
Returns the value of attribute camera.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def camera @camera end |
#deathmatch ⇒ Object
Returns the value of attribute deathmatch.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def deathmatch @deathmatch end |
#dynamic_lights ⇒ Object (readonly)
Returns the value of attribute dynamic_lights.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def dynamic_lights @dynamic_lights end |
#entities ⇒ Object (readonly)
Returns the value of attribute entities.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def entities @entities end |
#fraglimit ⇒ Object
Returns the value of attribute fraglimit.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def fraglimit @fraglimit end |
#game_time ⇒ Object
Returns the value of attribute game_time.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def game_time @game_time end |
#hud ⇒ Object (readonly)
Returns the value of attribute hud.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def hud @hud end |
#item_pickups ⇒ Object (readonly)
Returns the value of attribute item_pickups.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def item_pickups @item_pickups end |
#level ⇒ Object (readonly)
Returns the value of attribute level.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def level @level end |
#pak ⇒ Object (readonly)
Returns the value of attribute pak.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def pak @pak end |
#palette ⇒ Object (readonly)
Returns the value of attribute palette.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def palette @palette end |
#particles ⇒ Object (readonly)
Returns the value of attribute particles.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def particles @particles end |
#player ⇒ Object (readonly)
Returns the value of attribute player.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def player @player end |
#player_state ⇒ Object (readonly)
Returns the value of attribute player_state.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def player_state @player_state end |
#rj ⇒ Object
Returns the value of attribute rj.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def rj @rj end |
#samelevel ⇒ Object
Returns the value of attribute samelevel.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def samelevel @samelevel end |
#sound_events ⇒ Object (readonly)
Returns the value of attribute sound_events.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def sound_events @sound_events end |
#teamplay ⇒ Object
Returns the value of attribute teamplay.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def teamplay @teamplay end |
#temp1 ⇒ Object
Returns the value of attribute temp1.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def temp1 @temp1 end |
#timelimit ⇒ Object
Returns the value of attribute timelimit.
86 87 88 |
# File 'lib/quake/game/engine.rb', line 86 def timelimit @timelimit end |
#viewmodel ⇒ Object (readonly)
Returns the value of attribute viewmodel.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def viewmodel @viewmodel end |
#wad ⇒ Object (readonly)
Returns the value of attribute wad.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def wad @wad end |
#window ⇒ Object (readonly)
Returns the value of attribute window.
82 83 84 |
# File 'lib/quake/game/engine.rb', line 82 def window @window end |
Instance Method Details
#active_centerprint ⇒ Object
430 431 432 433 434 435 |
# File 'lib/quake/game/engine.rb', line 430 def active_centerprint return nil unless @centerprint return nil if @centerprint_expire.to_f <= @game_time @centerprint end |
#active_notify_lines ⇒ Object
437 438 439 440 |
# File 'lib/quake/game/engine.rb', line 437 def active_notify_lines (@notify_lines || []).select { |line| line[:expire] > @game_time } .map { |line| line[:text] } end |
#adjust_viewsize(delta) ⇒ Object
viewsize like Quake's +/- keys: 120 hides the bar, 110 shows the status bar only (default), 100 adds the inventory bar. Sub-100 sizes (shrunk 3D view) are not supported.
445 446 447 448 449 |
# File 'lib/quake/game/engine.rb', line 445 def adjust_viewsize(delta) @viewsize = ((@viewsize || DEFAULT_VIEWSIZE) + delta).clamp(100, 120) puts "viewsize #{@viewsize}" @viewsize end |
#clear_keys ⇒ Object
473 474 475 |
# File 'lib/quake/game/engine.rb', line 473 def clear_keys @keys = {} end |
#dump_state ⇒ Object
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'lib/quake/game/engine.rb', line 501 def dump_state { time: @game_time, map: @current_map, player: { position: vec_to_a(@player.position), velocity: vec_to_a(@player.velocity), yaw: @player.yaw, pitch: @player.pitch, on_ground: @player.on_ground, water_level: @player.water_level, noclip: @player.noclip }, stats: { health: @player_state.health, armor: @player_state.armor, armor_type: @player_state.armor_type, current_weapon: @player_state.current_weapon, ammo: @player_state.ammo.dup, attack_finished: @attack_finished }, brush_entities: brush_entity_summaries, particles: @particles ? @particles.particle_count : 0 } end |
#hud_stats ⇒ Object
Level statistics for the HUD (Quake's cl.stats STAT_MONSTERS / STAT_SECRETS etc. plus intermission state, sbar.c).
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
# File 'lib/quake/game/engine.rb', line 388 def hud_stats { monsters: @killed_monsters.to_i, total_monsters: @total_monsters.to_i, secrets: @brush_game&.found_secrets.to_i, total_secrets: @brush_game&.total_secrets.to_i, time: @game_time, level_name: @level_name, intermission: !!@intermission_running, completed_time: @intermission_start_time, sb_lines: sb_lines, centerprint: active_centerprint, notify_lines: active_notify_lines } end |
#keys ⇒ Object
477 478 479 |
# File 'lib/quake/game/engine.rb', line 477 def keys @keys end |
#load_map(map_name) ⇒ Object
Load a BSP map and (re)build all per-level state.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/quake/game/engine.rb', line 178 def load_map(map_name) bsp_data = @pak.read(map_name) raise "Map not found: #{map_name}" unless bsp_data @level = Bsp::Reader.new(bsp_data).parse @current_map = map_name configure_world_gravity(map_name) @entities = EntityParser.parse(@level.entities) @target_map = EntityParser.build_target_map(@entities) initialize_body_queue @projectiles = [] @temporary_dynamic_lights = [] @temporary_beams = [] @environment_damage_time = 0.0 @air_finished = @game_time + 12.0 @drown_damage = 2.0 @drown_pain_finished = 0.0 @player_in_water = false @bonus_cshift_percent = 0.0 @damage_cshift = Renderer::GLViewBlend::CShift.new(color: [0, 0, 0], percent: 0.0) @damage_kick_time = 0.0 @damage_kick_roll = 0.0 @damage_kick_pitch = 0.0 @weapon_punch_angle = Math::Vec3::ORIGIN @view_oldz = 0.0 @view_frame_dt = 0.0 @view_idle_scale = 0.0 @view_idealpitch = 0.0 @view_pitch_velocity = 0.0 @view_pitch_nodrift = true @view_pitch_driftmove = 0.0 @view_pitch_laststop = 0.0 @attack_finished = @game_time @jump_flag = 0.0 @notify_lines = [] @centerprint = nil @centerprint_expire = nil setup_misc_entities setup_ambient_sounds # Level stats for the HUD scoreboard/intermission (Quake's # total_monsters / killed_monsters, sbar.c STAT_* values). # Monsters count only entities that actually spawned (the # QuakeWorld-style monster stubs remove themselves at spawn). @killed_monsters = 0 @total_monsters = @entities.count do |ent| ent.classname.to_s.start_with?("monster_") && !ent.removed? end = world_info_value("message") @level_name = && !.empty? ? : File.basename(map_name, ".bsp") @intermission_start_time = nil set_player_spawn_point(select_spawn_point) # Load MDL models referenced by entities @mdl_cache ||= {} @entities.each { |ent| load_mdl_model(ent["model"]) unless ent.removed? } TEMP_ENTITY_MODELS.each { |model_path| load_mdl_model(model_path) } # Persistent player state across level loads @player_state ||= PlayerState.new @player_state.reset_spawn_runtime_fields apply_start_map_parms @item_pickups = ItemPickups.new(@entities, deathmatch: deathmatch) @brush_game = BrushEntities.new( @entities, @level, @target_map, sound_events: @sound_events, registered: @registered, serverflags: @player_state.serverflags, worldtype: current_worldtype ) # Player + camera (reset position to start) @player = Physics::Player.new(position: player_spawn_origin, yaw: @player_yaw) @player.gravity = current_gravity set_player_spawn_entity_state apply_put_client_in_server_spawn_effects @camera = Camera.new(position: player_eye_position, yaw: @player_yaw) build_renderers if @enable_render end |
#render ⇒ Object
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/quake/game/engine.rb', line 344 def render build_dynamic_lights @lightmap&.update(@game_time, lightstyles: current_lightstyles, dynamic_lights: @dynamic_lights) @world_renderer.render(@camera, @window.aspect_ratio, time: @game_time) @brush_renderer&.render(@entities, view_origin: @camera.position, time: @game_time, frustum: @camera.frustum_planes(@window.aspect_ratio)) @entities.each do |ent| next if ent.removed? next if @item_pickups.picked_up?(ent) emit_entity_effect_particles(ent) model_path = ent["model"] next unless model_path&.end_with?(".mdl") gl_model = @mdl_renderers[model_path] next unless gl_model ambient_light, shade_light = alias_entity_lighting(ent.position) gl_model.render( frame_index: ent.frame, lerp: 0.0, position: ent.position, yaw: alias_entity_yaw(ent, model_path), pitch: -ent.angles.x, roll: ent.angles.z, skin_index: ent.skin, time: @game_time + entity_sync_base(ent, gl_model), ambient_light: ambient_light, shade_light: shade_light ) end render_projectiles render_temp_beams @particles&.render(camera: @camera) render_viewmodel @world_renderer.render_water @view_blend&.render(current_view_blend) @hud&.render(@player_state, time: @game_time, stats: hud_stats) end |
#sb_lines ⇒ Object
451 452 453 454 455 456 457 |
# File 'lib/quake/game/engine.rb', line 451 def sb_lines size = @viewsize || DEFAULT_VIEWSIZE return 0 if size >= 120 return 24 if size >= 110 40 end |
#screenshot(filename) ⇒ Object
---------------------- debug output -----------------------
497 498 499 |
# File 'lib/quake/game/engine.rb', line 497 def screenshot(filename) Debug::Screenshot.save(filename, @window.width, @window.height) end |
#set_attack(pressed) ⇒ Object
481 482 483 |
# File 'lib/quake/game/engine.rb', line 481 def set_attack(pressed) @attack_pressed = pressed end |
#set_key(scancode, pressed) ⇒ Object
---------------------- input control ----------------------
465 466 467 |
# File 'lib/quake/game/engine.rb', line 465 def set_key(scancode, pressed) @keys[scancode] = pressed end |
#set_keys(keys_hash) ⇒ Object
469 470 471 |
# File 'lib/quake/game/engine.rb', line 469 def set_keys(keys_hash) @keys = keys_hash.dup end |
#shutdown ⇒ Object
527 528 529 530 531 532 533 |
# File 'lib/quake/game/engine.rb', line 527 def shutdown @sound_mixer&.close if @owns_window @window&.close end @pak.close end |
#sprint(text) ⇒ Object
QuakeC sprint(): queue a console notify line (top-left text, console.c Con_Print + Con_DrawNotify). Multi-line messages become one notify line each; only the last MAX_NOTIFY_LINES are kept.
407 408 409 410 411 412 413 414 415 |
# File 'lib/quake/game/engine.rb', line 407 def sprint(text) @notify_lines ||= [] text.to_s.split("\n").each do |line| next if line.empty? @notify_lines << { text: line, expire: @game_time + CON_NOTIFYTIME } @notify_lines.shift while @notify_lines.length > MAX_NOTIFY_LINES end end |
#swap_buffers ⇒ Object
459 460 461 |
# File 'lib/quake/game/engine.rb', line 459 def swap_buffers @window.swap end |
#teleport(x, y, z, yaw: nil, pitch: nil) ⇒ Object
---------------------- player control ---------------------
487 488 489 490 491 492 493 |
# File 'lib/quake/game/engine.rb', line 487 def teleport(x, y, z, yaw: nil, pitch: nil) @player.position = Math::Vec3.new(x.to_f, y.to_f, z.to_f) @player.velocity = Math::Vec3::ORIGIN @player.instance_variable_set(:@yaw, yaw.to_f) if yaw @player.instance_variable_set(:@pitch, pitch.to_f) if pitch sync_camera end |
#tick(dt) ⇒ Object
Update + render one frame.
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/quake/game/engine.rb', line 261 def tick(dt) @game_time += dt if @intermission_running intermission_think sync_camera return unless @enable_render render return end # Brush entities first (so collision uses current positions) if @brush_game @brush_game.update(dt, @player.position, player_state: @player_state) @brush_game.check_triggers(@player.position, player_forward: @player.forward_flat) do |trigger| handle_trigger(trigger) end snapped = @brush_game.snap_to_platform(@player.position) if snapped @player.position = snapped @player.on_ground = true @player.velocity = Math::Vec3.new(@player.velocity.x, @player.velocity.y, 0.0) end end solid_brush = @entities.select(&:brush_entity?) update_player_control(dt, solid_brush) @player_state.update_megahealth(@game_time) unless @item_pickups&.owns_megahealth_rot_for?(@player_state) update_start_items if @item_pickups @item_pickups.update(@game_time, player_state: @player_state).each do |evt| @sound_events&.on_pickup(evt) end end # Item pickups events = @item_pickups.check_pickups( @player.position, @player_state, game_time: @game_time, water_level: @player.water_level ) events.each do |evt| process_item_pickup_feedback(evt) process_item_pickup_targets(evt) end if player_postthink_active? check_powerup_warnings refresh_biosuit_air update_player_powerup_visual_state update_player_powerups check_no_ammo_weapon_switch fire_weapon if @attack_pressed && @game_time >= @attack_finished end update_triggered_misc_entities update_projectiles(dt) update_temporary_entities update_player_pain_animation update_player_death_animation check_rules if player_postthink_active? if @pending_changelevel && @game_time + 0.000001 >= @pending_changelevel_time.to_f run_pending_changelevel end # Viewmodel bob (before camera so bob is applied to camera too) if @viewmodel speed = ::Math.sqrt(@player.velocity.x**2 + @player.velocity.y**2) @viewmodel.update(dt, speed) end @view_frame_dt = dt sync_camera return unless @enable_render @world_renderer.update(dt) if @world_renderer.respond_to?(:update) @particles&.update(dt) update_view_cshifts(dt) render end |
#update_screen_messages ⇒ Object
Latch centerprints written to the player (QuakeC centerprint()) and drop expired on-screen text. Runs once per tick.
419 420 421 422 423 424 425 426 427 428 |
# File 'lib/quake/game/engine.rb', line 419 def = @player_state&.centerprint if && !.to_s.empty? @centerprint = @centerprint_expire = @game_time + CENTERPRINT_TIME @player_state.centerprint = nil end @centerprint = nil if @centerprint && @centerprint_expire.to_f <= @game_time @notify_lines&.reject! { |line| line[:expire] <= @game_time } end |