Class: Doom::Game::Intermission

Inherits:
Object
  • Object
show all
Includes:
FramebufferBlitter
Defined in:
lib/doom/game/intermission.rb

Overview

Intermission screen shown between levels. Displays kill%, item%, secret%, time, and par time.

Constant Summary collapse

PAR_TIMES =

Episode 1 par times in seconds (from Chocolate Doom)

{
  'E1M1' => 30, 'E1M2' => 75, 'E1M3' => 120, 'E1M4' => 90,
  'E1M5' => 165, 'E1M6' => 180, 'E1M7' => 180, 'E1M8' => 30, 'E1M9' => 165
}.freeze
NEXT_MAP =

Next map progression

{
  'E1M1' => 'E1M2', 'E1M2' => 'E1M3', 'E1M3' => 'E1M4', 'E1M4' => 'E1M5',
  'E1M5' => 'E1M6', 'E1M6' => 'E1M7', 'E1M7' => 'E1M8', 'E1M8' => nil,
  'E1M9' => 'E1M4'
}.freeze
COUNT_SPEED =

Counter animation speed (percentage points per tic)

2
TICS_PER_COUNT =
1

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from FramebufferBlitter

#blit_sprite

Constructor Details

#initialize(_wad, hud_graphics, stats) ⇒ Intermission

Returns a new instance of Intermission.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/doom/game/intermission.rb', line 31

def initialize(_wad, hud_graphics, stats)
  @gfx = hud_graphics
  @stats = stats # { map:, kills:, total_kills:, items:, total_items:, secrets:, total_secrets:, time_tics: }
  @finished = false
  @next_map = NEXT_MAP[stats[:map]]
  @tic = 0

  # Animated counters (count up from 0 to actual value)
  @kill_count = 0
  @item_count = 0
  @secret_count = 0
  @time_count = 0
  @counting_done = false

  # Target percentages
  @kill_pct = @stats[:total_kills] > 0 ? (@stats[:kills] * 100 / @stats[:total_kills]) : 100
  @item_pct = @stats[:total_items] > 0 ? (@stats[:items] * 100 / @stats[:total_items]) : 100
  @secret_pct = @stats[:total_secrets] > 0 ? (@stats[:secrets] * 100 / @stats[:total_secrets]) : 100
  @time_secs = @stats[:time_tics] / 35

  @par_time = PAR_TIMES[stats[:map]] || 0

  load_graphics
end

Instance Attribute Details

#finishedObject (readonly)

Returns the value of attribute finished.



29
30
31
# File 'lib/doom/game/intermission.rb', line 29

def finished
  @finished
end

#next_mapObject (readonly)

Returns the value of attribute next_map.



29
30
31
# File 'lib/doom/game/intermission.rb', line 29

def next_map
  @next_map
end

Instance Method Details

#handle_keyObject



123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/doom/game/intermission.rb', line 123

def handle_key
  if @counting_done
    @finished = true
  else
    # Skip counting animation
    @kill_count = @kill_pct
    @item_count = @item_pct
    @secret_count = @secret_pct
    @time_count = @time_secs
    @counting_done = true
  end
end

#render(framebuffer) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
# File 'lib/doom/game/intermission.rb', line 74

def render(framebuffer)
  # Background
  draw_background(framebuffer)

  # "Finished" text + level name
  draw_sprite(framebuffer, @wifinish, 64, 4) if @wifinish
  level_idx = map_to_level_index(@stats[:map])
  lv = @level_names[level_idx]
  draw_sprite(framebuffer, lv, (320 - (lv&.width || 0)) / 2, 24) if lv

  # Kill, Item, Secret percentages
  y = 60
  draw_sprite(framebuffer, @wiostk, 50, y) if @wiostk
  draw_percent(framebuffer, 260, y, @kill_count)

  y += 24
  draw_sprite(framebuffer, @wiosti, 50, y) if @wiosti
  draw_percent(framebuffer, 260, y, @item_count)

  y += 24
  draw_sprite(framebuffer, @wiosts, 50, y) if @wiosts
  draw_percent(framebuffer, 260, y, @secret_count)

  # Time
  y += 30
  draw_sprite(framebuffer, @witime, 16, y) if @witime
  draw_time(framebuffer, 160, y, @time_count)

  # Par time
  draw_sprite(framebuffer, @wipar, 176, y) if @wipar
  draw_time(framebuffer, 292, y, @par_time)

  # "Entering" next level (after counting done)
  if @counting_done && @next_map
    y += 30
    draw_sprite(framebuffer, @wienter, 64, y) if @wienter
    next_idx = map_to_level_index(@next_map)
    nlv = @level_names[next_idx]
    draw_sprite(framebuffer, nlv, (320 - (nlv&.width || 0)) / 2, y + 18) if nlv
  end

  # "Press any key" hint after counting
  return unless @counting_done && (@tic / 17).even?

  # Blink hint via skull
  skull = @skulls[@tic / 8 % 2]
  draw_sprite(framebuffer, skull, 144, 210) if skull
end

#updateObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/doom/game/intermission.rb', line 56

def update
  @tic += 1
  return if @counting_done

  # Animate counters
  if @kill_count < @kill_pct
    @kill_count = [@kill_count + COUNT_SPEED, @kill_pct].min
  elsif @item_count < @item_pct
    @item_count = [@item_count + COUNT_SPEED, @item_pct].min
  elsif @secret_count < @secret_pct
    @secret_count = [@secret_count + COUNT_SPEED, @secret_pct].min
  elsif @time_count < @time_secs
    @time_count = [@time_count + 3, @time_secs].min
  else
    @counting_done = true
  end
end