doom 0.8.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +17 -0
  3. data/README.md +65 -4
  4. data/bin/doom +134 -24
  5. data/lib/doom/benchmark.rb +282 -0
  6. data/lib/doom/game/animations.rb +9 -2
  7. data/lib/doom/game/combat.rb +239 -153
  8. data/lib/doom/game/framebuffer_blitter.rb +38 -0
  9. data/lib/doom/game/geometry.rb +68 -0
  10. data/lib/doom/game/intermission.rb +22 -39
  11. data/lib/doom/game/item_pickup.rb +87 -75
  12. data/lib/doom/game/menu.rb +90 -85
  13. data/lib/doom/game/monster_ai.rb +150 -136
  14. data/lib/doom/game/player.rb +105 -0
  15. data/lib/doom/game/player_physics.rb +384 -0
  16. data/lib/doom/game/player_state.rb +38 -64
  17. data/lib/doom/game/random.rb +82 -0
  18. data/lib/doom/game/sector_actions.rb +169 -93
  19. data/lib/doom/game/sector_effects.rb +25 -18
  20. data/lib/doom/game/snapshot.rb +584 -0
  21. data/lib/doom/game/sound_engine.rb +33 -58
  22. data/lib/doom/game/state_hash.rb +125 -0
  23. data/lib/doom/game/ticcmd.rb +61 -0
  24. data/lib/doom/game/world.rb +420 -0
  25. data/lib/doom/map/data.rb +95 -0
  26. data/lib/doom/net/client.rb +204 -0
  27. data/lib/doom/net/desync_monitor.rb +101 -0
  28. data/lib/doom/net/game_server.rb +232 -0
  29. data/lib/doom/net/lockstep.rb +170 -0
  30. data/lib/doom/net/protocol.rb +350 -0
  31. data/lib/doom/net/session.rb +282 -0
  32. data/lib/doom/net/transport.rb +110 -0
  33. data/lib/doom/platform/gosu_window.rb +604 -832
  34. data/lib/doom/platform/sdl.rb +74 -0
  35. data/lib/doom/platform/window_logic.rb +61 -0
  36. data/lib/doom/render/font.rb +5 -3
  37. data/lib/doom/render/hardware_renderer.rb +547 -0
  38. data/lib/doom/render/ray_tracing/bvh.rb +103 -0
  39. data/lib/doom/render/ray_tracing/material_state.rb +66 -0
  40. data/lib/doom/render/ray_tracing/texture_atlas.rb +78 -0
  41. data/lib/doom/render/ray_tracing_renderer.rb +940 -0
  42. data/lib/doom/render/renderer.rb +466 -440
  43. data/lib/doom/render/renderer_factory.rb +50 -0
  44. data/lib/doom/render/screen_melt.rb +7 -7
  45. data/lib/doom/render/spinel_native/kernel.rb +780 -0
  46. data/lib/doom/render/spinel_native_renderer.rb +162 -0
  47. data/lib/doom/render/status_bar.rb +14 -10
  48. data/lib/doom/render/weapon_renderer.rb +9 -10
  49. data/lib/doom/render/world_mesh.rb +270 -0
  50. data/lib/doom/render/zbuffer_renderer.rb +151 -0
  51. data/lib/doom/version.rb +1 -1
  52. data/lib/doom/wad/flat.rb +1 -1
  53. data/lib/doom/wad/hud_graphics.rb +7 -3
  54. data/lib/doom/wad/palette.rb +3 -3
  55. data/lib/doom/wad/patch.rb +1 -1
  56. data/lib/doom/wad/reader.rb +12 -15
  57. data/lib/doom/wad/sound.rb +14 -6
  58. data/lib/doom/wad/sprite.rb +36 -35
  59. data/lib/doom/wad/texture.rb +5 -5
  60. data/lib/doom/wad_downloader.rb +38 -56
  61. data/lib/doom.rb +197 -16
  62. metadata +94 -7
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doom
4
+ module Render
5
+ module RayTracing
6
+ # Resolves animated WAD materials and packs per-surface flags into the
7
+ # float shared with sector light level in the GPU triangle texture.
8
+ class MaterialState
9
+ EMISSIVE_FLAG = 1_024.0
10
+ MASKED_FLAG = 2_048.0
11
+ REFLECTIVE_FLAG = 4_096.0
12
+ REFRACTIVE_FLAG = 8_192.0
13
+ EMISSIVE_PATTERN = /\A(?:NUKAGE|SLIME|LAVA)/
14
+ LIQUID_PATTERN = /\A(?:NUKAGE|SLIME|LAVA|FWATER|SWATER|BLOOD)/
15
+ REFLECTIVE_PATTERN = /#{LIQUID_PATTERN.source}|(?:METAL|SILVER|COMP|TEK|SUPPORT)/
16
+ REFRACTIVE_PATTERN = LIQUID_PATTERN
17
+
18
+ def initialize(flats, animations)
19
+ @flats = flats
20
+ @animations = animations
21
+ end
22
+
23
+ def animation_signature
24
+ return nil unless @animations
25
+
26
+ [@animations.flat_translation.values, @animations.texture_translation.values]
27
+ end
28
+
29
+ def animation_names
30
+ return [] unless @animations
31
+ return @animations.frame_names if @animations.respond_to?(:frame_names)
32
+
33
+ [@animations.flat_translation, @animations.texture_translation]
34
+ .flat_map { |translation| translation.keys + translation.values }
35
+ end
36
+
37
+ def resolve(name)
38
+ return name unless @animations
39
+
40
+ @flats.key?(name) ? @animations.translate_flat(name) : @animations.translate_texture(name)
41
+ end
42
+
43
+ def emissive?(name)
44
+ name&.match?(EMISSIVE_PATTERN) || false
45
+ end
46
+
47
+ def reflective?(name)
48
+ name&.match?(REFLECTIVE_PATTERN) || false
49
+ end
50
+
51
+ def refractive?(name)
52
+ name&.match?(REFRACTIVE_PATTERN) || false
53
+ end
54
+
55
+ def encoded_light(triangle)
56
+ value = triangle.light.to_f
57
+ value += EMISSIVE_FLAG if emissive?(triangle.material)
58
+ value += MASKED_FLAG if triangle.masked
59
+ value += REFLECTIVE_FLAG if reflective?(triangle.material)
60
+ value += REFRACTIVE_FLAG if refractive?(triangle.material)
61
+ value
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doom
4
+ module Render
5
+ module RayTracing
6
+ # Packs palette-indexed flats and composite wall textures into one RGBA
7
+ # texture. Rectangle entries are [x, y, width, height, texel_w, texel_h].
8
+ class TextureAtlas
9
+ attr_reader :size
10
+
11
+ def initialize(size:, textures:, flats:, palette:)
12
+ @size = size
13
+ @textures = textures
14
+ @flats = flats
15
+ @palette = palette
16
+ end
17
+
18
+ def build(material_names)
19
+ pixels = "\0" * (@size * @size * 4)
20
+ rectangles = {}
21
+ x = y = row_height = 0
22
+ material_names.uniq.each do |name|
23
+ source = source_for(name)
24
+ next unless source
25
+
26
+ width, height, rgba = source
27
+ if x + width > @size
28
+ x = 0
29
+ y += row_height
30
+ row_height = 0
31
+ end
32
+ raise ArgumentError, 'ray texture atlas overflow' if y + height > @size
33
+
34
+ height.times do |row|
35
+ destination = (((y + row) * @size) + x) * 4
36
+ pixels[destination, width * 4] = rgba.byteslice(row * width * 4, width * 4)
37
+ end
38
+ rectangles[name] = [x.to_f / @size, y.to_f / @size,
39
+ width.to_f / @size, height.to_f / @size,
40
+ width.to_f, height.to_f]
41
+ x += width
42
+ row_height = [row_height, height].max
43
+ end
44
+ [pixels, rectangles]
45
+ end
46
+
47
+ private
48
+
49
+ def source_for(name)
50
+ source = @flats[name] || @textures[name]
51
+ return unless source
52
+
53
+ width = source.width
54
+ height = source.height
55
+ indices = if source.respond_to?(:column_pixels)
56
+ columns_to_rows(source, width, height)
57
+ else
58
+ source.pixels
59
+ end
60
+ rgba = indices.map do |index|
61
+ index.nil? ? "\0\0\0\0" : [*@palette.colors[index], 255].pack('C4')
62
+ end.join
63
+ [width, height, rgba]
64
+ end
65
+
66
+ def columns_to_rows(source, width, height)
67
+ pixels = Array.new(width * height)
68
+ width.times do |column|
69
+ source.column_pixels(column).each_with_index do |value, row|
70
+ pixels[(row * width) + column] = value if row < height
71
+ end
72
+ end
73
+ pixels
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end