Class: Doom::Render::ScreenMelt
- Inherits:
-
Object
- Object
- Doom::Render::ScreenMelt
- Defined in:
- lib/doom/render/screen_melt.rb
Overview
DOOM’s screen melt/wipe effect from wipe.c. Each column slides down at a slightly different speed, revealing the new screen underneath.
Constant Summary collapse
- WIDTH =
SCREEN_WIDTH- HEIGHT =
SCREEN_HEIGHT- MELT_SPEED =
~8 pixels per frame (Chocolate Doom does HEIGHT/15 at 35fps)
HEIGHT / 30
Instance Method Summary collapse
- #done? ⇒ Boolean
-
#initialize(old_screen, new_screen) ⇒ ScreenMelt
constructor
A new instance of ScreenMelt.
-
#update(framebuffer) ⇒ Object
Advance one tic.
Constructor Details
#initialize(old_screen, new_screen) ⇒ ScreenMelt
Returns a new instance of ScreenMelt.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/doom/render/screen_melt.rb', line 13 def initialize(old_screen, new_screen) # Snapshot both screens (arrays of palette indices, 320x240) @old = old_screen.dup @new = new_screen.dup @done = false # Initialize column offsets (from wipe_initMelt in wipe.c) # Column 0 gets random negative offset, each subsequent column # varies by -1/0/+1 from previous, creating a jagged melt line @y = Array.new(WIDTH) @y[0] = -(rand(16)) (1...WIDTH).each do |i| @y[i] = @y[i - 1] + (rand(3) - 1) @y[i] = -15 if @y[i] < -15 @y[i] = 0 if @y[i] > 0 end end |
Instance Method Details
#done? ⇒ Boolean
31 32 33 |
# File 'lib/doom/render/screen_melt.rb', line 31 def done? @done end |
#update(framebuffer) ⇒ Object
Advance one tic. Returns the composited framebuffer.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/doom/render/screen_melt.rb', line 36 def update(framebuffer) all_done = true WIDTH.times do |x| if @y[x] < 0 @y[x] += 1 all_done = false # Column hasn't started melting yet - show old screen HEIGHT.times { |row| framebuffer[row * WIDTH + x] = @old[row * WIDTH + x] } elsif @y[x] < HEIGHT all_done = false dy = @y[x] # Top part: new screen revealed dy.times do |row| framebuffer[row * WIDTH + x] = @new[row * WIDTH + x] end # Bottom part: old screen shifted down (dy...HEIGHT).each do |row| src_row = row - dy framebuffer[row * WIDTH + x] = @old[src_row * WIDTH + x] end @y[x] += MELT_SPEED else # Column fully melted - show new screen HEIGHT.times { |row| framebuffer[row * WIDTH + x] = @new[row * WIDTH + x] } end end @done = all_done end |