doom 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 77ff94b86295598915c520657fb36512c6fc091d24d6660cc8dea588a8939062
4
+ data.tar.gz: 3b3632ab2f9adbd0d8d4078c71f5c9f941943dd30d96c951bb27e803256a87d1
5
+ SHA512:
6
+ metadata.gz: 61d4a1cf4f3542c3ce93d4dc624b2cc36c4d93be39a9d65cc832198be7bbd04b9bd86cc7723d13181b80907809005571d7a9f85217e628d6f5a5b7a02e35908a
7
+ data.tar.gz: 514bc92b65f0934cbf31828e4553d6978d86932afa690f70b89a69ed6d6bbe71cb98e0d3bfbe86916e0c799498366eedcad2f74904f78be84fc3d559f43a8dd3
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Chris Hasiński
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # Ruby Doom
2
+
3
+ A Ruby gem that ports the classic Doom game to Ruby, focusing on core gameplay without sound or networking features.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'doom'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ $ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ $ gem install doom
23
+ ```
24
+
25
+ ## Requirements
26
+
27
+ - Ruby 2.6 or higher
28
+ - A legal copy of Doom for the WAD files (e.g., DOOM.WAD)
29
+
30
+ ## Usage
31
+
32
+ ### Command Line Interface
33
+
34
+ The gem includes two command-line tools:
35
+
36
+ #### WAD Explorer
37
+
38
+ The `wad` command allows you to explore WAD files:
39
+
40
+ ```bash
41
+ # Show general information about a WAD file
42
+ $ wad -i DOOM.WAD
43
+
44
+ # List all maps in a WAD file
45
+ $ wad -l DOOM.WAD
46
+
47
+ # Show details for a specific map
48
+ $ wad -m E1M1 DOOM.WAD
49
+
50
+ # List all textures in a WAD file
51
+ $ wad -t DOOM.WAD
52
+
53
+ # Show details for a specific texture
54
+ $ wad -x STARTAN1 DOOM.WAD
55
+
56
+ # List all sprites in a WAD file
57
+ $ wad -s DOOM.WAD
58
+
59
+ # Show details for a specific sprite
60
+ $ wad -p TROOA1 DOOM.WAD
61
+
62
+ # Show help
63
+ $ wad -h
64
+ ```
65
+
66
+ #### Game Launcher
67
+
68
+ The `doom` command allows you to start the game:
69
+
70
+ ```bash
71
+ # Start the game with default settings
72
+ $ doom DOOM.WAD
73
+
74
+ # Start the game with a specific map
75
+ $ doom -m E1M1 DOOM.WAD
76
+
77
+ # Start the game with a custom window size
78
+ $ doom -w 800 -h 600 DOOM.WAD
79
+
80
+ # Start the game in fullscreen mode
81
+ $ doom -f DOOM.WAD
82
+
83
+ # Show help
84
+ $ doom --help
85
+ ```
86
+
87
+ ### Ruby API
88
+
89
+ You can also use the Ruby API in your own code:
90
+
91
+ ```ruby
92
+ require 'doom'
93
+
94
+ # Load a WAD file
95
+ loaders = Doom.load_wad('path/to/DOOM.WAD')
96
+
97
+ # Access WAD information
98
+ wad_loader = loaders[:wad]
99
+ puts "WAD type: #{wad_loader.wad_type}"
100
+ puts "Number of lumps: #{wad_loader.lumps.size}"
101
+
102
+ # Access map information
103
+ map_loader = loaders[:maps]
104
+ puts "Available maps: #{map_loader.maps.join(', ')}"
105
+
106
+ # Load a specific map
107
+ map_data = map_loader.load_map('E1M1')
108
+ puts "Number of things in E1M1: #{map_data[:things].size}"
109
+
110
+ # Access texture information
111
+ texture_loader = loaders[:textures]
112
+ puts "Available textures: #{texture_loader.texture_names.join(', ')}"
113
+
114
+ # Access sprite information
115
+ sprite_loader = loaders[:sprites]
116
+ puts "Available sprites: #{sprite_loader.sprite_names.join(', ')}"
117
+ ```
118
+
119
+ ## Features
120
+
121
+ ### Phase 1: WAD File Loader
122
+
123
+ - WAD file parsing
124
+ - Map data extraction
125
+ - Texture information parsing
126
+ - Sprite data handling
127
+
128
+ ### Phase 2: Rendering Engine (Current)
129
+
130
+ - Window management
131
+ - BSP rendering
132
+ - Texture mapping
133
+ - Sprite rendering
134
+ - HUD implementation
135
+ - Basic game loop
136
+
137
+ ### Future Phases
138
+
139
+ - Game mechanics
140
+ - Advanced game loop and state management
141
+ - Polishing
142
+
143
+ ## Development
144
+
145
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
146
+
147
+ To install this gem onto your local machine, run `bundle exec rake install`.
148
+
149
+ ## Contributing
150
+
151
+ Bug reports and pull requests are welcome on GitHub at https://github.com/khasinski/doom-rb.
152
+
153
+ ## License
154
+
155
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
156
+
157
+ ## Legal
158
+
159
+ Users must own a legal copy of Doom for the WAD files. This project complies with id Software's terms regarding Doom content.
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "doom"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/doom ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "doom"
6
+ require "optparse"
7
+
8
+ options = {
9
+ map: nil,
10
+ width: 640,
11
+ height: 480,
12
+ fullscreen: false
13
+ }
14
+
15
+ parser = OptionParser.new do |opts|
16
+ opts.banner = "Usage: doom [options] WAD_FILE"
17
+
18
+ opts.on("-m", "--map MAP", "Start the game with a specific map") do |map|
19
+ options[:map] = map
20
+ end
21
+
22
+ opts.on("-w", "--width WIDTH", Integer, "Set the window width (default: 640)") do |width|
23
+ options[:width] = width
24
+ end
25
+
26
+ opts.on("-h", "--height HEIGHT", Integer, "Set the window height (default: 480)") do |height|
27
+ options[:height] = height
28
+ end
29
+
30
+ opts.on("-f", "--fullscreen", "Start in fullscreen mode") do
31
+ options[:fullscreen] = true
32
+ end
33
+
34
+ opts.on("--help", "Show this help message") do
35
+ puts opts
36
+ exit
37
+ end
38
+ end
39
+
40
+ parser.parse!
41
+
42
+ if ARGV.empty?
43
+ puts "Error: WAD file is required"
44
+ puts parser
45
+ exit 1
46
+ end
47
+
48
+ wad_file = ARGV[0]
49
+ unless File.exist?(wad_file)
50
+ puts "Error: WAD file '#{wad_file}' not found"
51
+ exit 1
52
+ end
53
+
54
+ begin
55
+ puts "Starting Doom with WAD file: #{wad_file}"
56
+ puts "Map: #{options[:map] || 'Default'}"
57
+ puts "Window size: #{options[:width]}x#{options[:height]}"
58
+ puts "Fullscreen: #{options[:fullscreen]}"
59
+
60
+ Doom.start_game(
61
+ wad_file,
62
+ options[:map],
63
+ options[:width],
64
+ options[:height],
65
+ options[:fullscreen]
66
+ )
67
+ rescue Doom::Error => e
68
+ puts "Error: #{e.message}"
69
+ exit 1
70
+ end
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other setup tasks here
data/bin/wad ADDED
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "doom"
6
+ require "optparse"
7
+
8
+ options = {
9
+ action: nil,
10
+ map: nil,
11
+ texture: nil,
12
+ sprite: nil
13
+ }
14
+
15
+ parser = OptionParser.new do |opts|
16
+ opts.banner = "Usage: wad [options] WAD_FILE"
17
+
18
+ opts.on("-l", "--list-maps", "List all maps in the WAD file") do
19
+ options[:action] = :list_maps
20
+ end
21
+
22
+ opts.on("-m", "--map MAP", "Show details for a specific map") do |map|
23
+ options[:action] = :show_map
24
+ options[:map] = map
25
+ end
26
+
27
+ opts.on("-t", "--list-textures", "List all textures in the WAD file") do
28
+ options[:action] = :list_textures
29
+ end
30
+
31
+ opts.on("-x", "--texture TEXTURE", "Show details for a specific texture") do |texture|
32
+ options[:action] = :show_texture
33
+ options[:texture] = texture
34
+ end
35
+
36
+ opts.on("-s", "--list-sprites", "List all sprites in the WAD file") do
37
+ options[:action] = :list_sprites
38
+ end
39
+
40
+ opts.on("-p", "--sprite SPRITE", "Show details for a specific sprite") do |sprite|
41
+ options[:action] = :show_sprite
42
+ options[:sprite] = sprite
43
+ end
44
+
45
+ opts.on("-i", "--info", "Show general information about the WAD file") do
46
+ options[:action] = :show_info
47
+ end
48
+
49
+ opts.on("-h", "--help", "Show this help message") do
50
+ puts opts
51
+ exit
52
+ end
53
+ end
54
+
55
+ parser.parse!
56
+
57
+ if ARGV.empty?
58
+ puts "Error: WAD file is required"
59
+ puts parser
60
+ exit 1
61
+ end
62
+
63
+ wad_file = ARGV[0]
64
+ unless File.exist?(wad_file)
65
+ puts "Error: WAD file '#{wad_file}' not found"
66
+ exit 1
67
+ end
68
+
69
+ begin
70
+ loaders = Doom.load_wad(wad_file)
71
+
72
+ case options[:action]
73
+ when :list_maps
74
+ puts "Maps in #{wad_file}:"
75
+ loaders[:maps].maps.each do |map|
76
+ puts " #{map}"
77
+ end
78
+
79
+ when :show_map
80
+ map_name = options[:map]
81
+ if loaders[:maps].maps.include?(map_name)
82
+ map_data = loaders[:maps].load_map(map_name)
83
+ puts "Map: #{map_name}"
84
+ puts " Things: #{map_data[:things].size}"
85
+ puts " Linedefs: #{map_data[:linedefs].size}"
86
+ puts " Sidedefs: #{map_data[:sidedefs].size}"
87
+ puts " Vertexes: #{map_data[:vertexes].size}"
88
+ puts " Sectors: #{map_data[:sectors].size}"
89
+ else
90
+ puts "Error: Map '#{map_name}' not found"
91
+ exit 1
92
+ end
93
+
94
+ when :list_textures
95
+ puts "Textures in #{wad_file}:"
96
+ loaders[:textures].texture_names.each do |texture|
97
+ puts " #{texture}"
98
+ end
99
+
100
+ when :show_texture
101
+ texture_name = options[:texture]
102
+ if loaders[:textures].texture_exists?(texture_name)
103
+ texture_data = loaders[:textures].get_texture(texture_name)
104
+ puts "Texture: #{texture_name}"
105
+ puts " Width: #{texture_data[:width]}"
106
+ puts " Height: #{texture_data[:height]}"
107
+ puts " Patches: #{texture_data[:patches].size}"
108
+ texture_data[:patches].each_with_index do |patch, i|
109
+ puts " Patch #{i + 1}: #{patch[:patch_name]} (#{patch[:x_offset]}, #{patch[:y_offset]})"
110
+ end
111
+ else
112
+ puts "Error: Texture '#{texture_name}' not found"
113
+ exit 1
114
+ end
115
+
116
+ when :list_sprites
117
+ puts "Sprites in #{wad_file}:"
118
+ loaders[:sprites].sprite_names.each do |sprite|
119
+ puts " #{sprite}"
120
+ end
121
+
122
+ when :show_sprite
123
+ sprite_name = options[:sprite]
124
+ if loaders[:sprites].sprite_exists?(sprite_name)
125
+ sprite_data = loaders[:sprites].get_sprite(sprite_name)
126
+ puts "Sprite: #{sprite_name}"
127
+ puts " Width: #{sprite_data[:width]}"
128
+ puts " Height: #{sprite_data[:height]}"
129
+ puts " Offset: (#{sprite_data[:left_offset]}, #{sprite_data[:top_offset]})"
130
+ else
131
+ puts "Error: Sprite '#{sprite_name}' not found"
132
+ exit 1
133
+ end
134
+
135
+ when :show_info
136
+ puts "WAD File: #{wad_file}"
137
+ puts "Type: #{loaders[:wad].wad_type}"
138
+ puts "Directory entries: #{loaders[:wad].directory.size}"
139
+ puts "Lumps: #{loaders[:wad].lumps.size}"
140
+ puts "Maps: #{loaders[:maps].maps.size}"
141
+ puts "Textures: #{loaders[:textures].texture_names.size}"
142
+ puts "Sprites: #{loaders[:sprites].sprite_names.size}"
143
+
144
+ else
145
+ puts "Please specify an action. Use --help for options."
146
+ exit 1
147
+ end
148
+
149
+ rescue Doom::Error => e
150
+ puts "Error: #{e.message}"
151
+ exit 1
152
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doom
4
+ # BSPRenderer is responsible for rendering the level using Binary Space Partitioning
5
+ class BSPRenderer < Renderer
6
+ attr_reader :map_loader
7
+
8
+ # Initialize a new BSPRenderer with the given window and map loader
9
+ # @param window [Doom::Window] the window to render to
10
+ # @param map_loader [Doom::MapLoader] the map loader to use
11
+ def initialize(window, map_loader)
12
+ super(window)
13
+ @map_loader = map_loader
14
+ @current_map = nil
15
+ end
16
+
17
+ # Load a specific map
18
+ # @param map_name [String] the name of the map to load
19
+ def load_map(map_name)
20
+ @current_map = @map_loader.load_map(map_name)
21
+ end
22
+
23
+ # Render the current map
24
+ def render
25
+ return unless @current_map
26
+
27
+ # In a real implementation, this would:
28
+ # 1. Determine the player's position and angle
29
+ # 2. Traverse the BSP tree to find visible walls
30
+ # 3. Render the walls with texture mapping
31
+ # 4. Render sprites (enemies, items, etc.)
32
+
33
+ # For now, we'll just render a simple wireframe of the map
34
+ render_wireframe
35
+ end
36
+
37
+ private
38
+
39
+ # Render a simple wireframe of the map
40
+ def render_wireframe
41
+ # Get the vertexes and linedefs from the current map
42
+ vertexes = @current_map[:vertexes]
43
+ linedefs = @current_map[:linedefs]
44
+
45
+ # Calculate scale and offset to fit the map in the window
46
+ scale, offset_x, offset_y = calculate_scale_and_offset(vertexes)
47
+
48
+ # Draw each linedef as a line
49
+ linedefs.each do |linedef|
50
+ start_vertex = vertexes[linedef[:start_vertex]]
51
+ end_vertex = vertexes[linedef[:end_vertex]]
52
+
53
+ # Transform the vertexes to screen coordinates
54
+ x1 = offset_x + start_vertex[:x] * scale
55
+ y1 = offset_y + start_vertex[:y] * scale
56
+ x2 = offset_x + end_vertex[:x] * scale
57
+ y2 = offset_y + end_vertex[:y] * scale
58
+
59
+ # Draw the line
60
+ @window.draw_line(x1, y1, Gosu::Color::WHITE, x2, y2, Gosu::Color::WHITE)
61
+ end
62
+ end
63
+
64
+ # Calculate the scale and offset to fit the map in the window
65
+ # @param vertexes [Array<Hash>] the vertexes of the map
66
+ # @return [Array<Float, Float, Float>] the scale, offset_x, and offset_y
67
+ def calculate_scale_and_offset(vertexes)
68
+ # Find the min and max coordinates
69
+ min_x = vertexes.map { |v| v[:x] }.min
70
+ max_x = vertexes.map { |v| v[:x] }.max
71
+ min_y = vertexes.map { |v| v[:y] }.min
72
+ max_y = vertexes.map { |v| v[:y] }.max
73
+
74
+ # Calculate the width and height of the map
75
+ map_width = max_x - min_x
76
+ map_height = max_y - min_y
77
+
78
+ # Calculate the scale to fit the map in the window
79
+ scale_x = @window.width * 0.8 / map_width
80
+ scale_y = @window.height * 0.8 / map_height
81
+ scale = [scale_x, scale_y].min
82
+
83
+ # Calculate the offset to center the map
84
+ offset_x = (@window.width - map_width * scale) / 2 - min_x * scale
85
+ offset_y = (@window.height - map_height * scale) / 2 - min_y * scale
86
+
87
+ [scale, offset_x, offset_y]
88
+ end
89
+ end
90
+ end
data/lib/doom/game.rb ADDED
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doom
4
+ # Game is the main class that ties everything together
5
+ class Game
6
+ attr_reader :window, :loaders, :renderers
7
+
8
+ # Initialize a new Game with the given WAD file
9
+ # @param wad_file [String] the path to the WAD file
10
+ # @param width [Integer] the width of the window
11
+ # @param height [Integer] the height of the window
12
+ # @param fullscreen [Boolean] whether the window should be fullscreen
13
+ def initialize(wad_file, width = 640, height = 480, fullscreen = false)
14
+ @wad_file = wad_file
15
+ @width = width
16
+ @height = height
17
+ @fullscreen = fullscreen
18
+ @loaders = {}
19
+ @renderers = {}
20
+ @current_map = nil
21
+ @player_data = {
22
+ health: 100,
23
+ armor: 0,
24
+ ammo: 50,
25
+ weapon: "Pistol"
26
+ }
27
+ end
28
+
29
+ # Start the game
30
+ # @param map_name [String] the name of the map to start on
31
+ def start(map_name = nil)
32
+ load_wad
33
+ setup_window
34
+ setup_renderers
35
+ load_map(map_name) if map_name
36
+ @window.show
37
+ end
38
+
39
+ # Load the WAD file
40
+ def load_wad
41
+ @loaders = Doom.load_wad(@wad_file)
42
+ end
43
+
44
+ # Setup the window
45
+ def setup_window
46
+ @window = Window.new(@width, @height, @fullscreen)
47
+ @window.game = self
48
+ end
49
+
50
+ # Setup the renderers
51
+ def setup_renderers
52
+ @renderers[:bsp] = BSPRenderer.new(@window, @loaders[:maps])
53
+ @renderers[:texture] = TextureMapper.new(@loaders[:textures])
54
+ @renderers[:sprite] = SpriteRenderer.new(@loaders[:sprites])
55
+ @renderers[:hud] = HUD.new(@window)
56
+ end
57
+
58
+ # Load a specific map
59
+ # @param map_name [String] the name of the map to load
60
+ def load_map(map_name)
61
+ @current_map = map_name
62
+ @renderers[:bsp].load_map(map_name)
63
+ end
64
+
65
+ # Update the game state
66
+ def update
67
+ # Will be implemented in Phase 3
68
+ end
69
+
70
+ # Draw the game
71
+ def draw
72
+ @renderers[:bsp].render if @current_map
73
+ @renderers[:hud].render(@player_data)
74
+ end
75
+
76
+ # Handle button press events
77
+ def button_down(id)
78
+ case id
79
+ when Gosu::KB_ESCAPE
80
+ @window.close
81
+ end
82
+ end
83
+ end
84
+ end
data/lib/doom/hud.rb ADDED
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doom
4
+ # HUD is responsible for rendering the Heads-Up Display
5
+ class HUD
6
+ attr_reader :window
7
+
8
+ # Initialize a new HUD with the given window
9
+ # @param window [Doom::Window] the window to render to
10
+ def initialize(window)
11
+ @window = window
12
+ @font = Gosu::Font.new(20)
13
+ end
14
+
15
+ # Render the HUD
16
+ # @param player_data [Hash] the player data to display
17
+ def render(player_data = {})
18
+ # In a real implementation, this would render:
19
+ # - Health
20
+ # - Armor
21
+ # - Ammo
22
+ # - Weapons
23
+ # - Face
24
+ # - Keys
25
+ # - etc.
26
+
27
+ # For now, we'll just render some placeholder text
28
+ health = player_data[:health] || 100
29
+ armor = player_data[:armor] || 0
30
+ ammo = player_data[:ammo] || 50
31
+ weapon = player_data[:weapon] || "Pistol"
32
+
33
+ # Draw the HUD background
34
+ draw_background
35
+
36
+ # Draw the HUD elements
37
+ draw_health(health)
38
+ draw_armor(armor)
39
+ draw_ammo(ammo)
40
+ draw_weapon(weapon)
41
+ end
42
+
43
+ private
44
+
45
+ # Draw the HUD background
46
+ def draw_background
47
+ color = Gosu::Color.new(128, 0, 0, 0) # Semi-transparent black
48
+ @window.draw_quad(
49
+ 0, @window.height - 80, color,
50
+ @window.width, @window.height - 80, color,
51
+ @window.width, @window.height, color,
52
+ 0, @window.height, color
53
+ )
54
+ end
55
+
56
+ # Draw the health display
57
+ # @param health [Integer] the player's health
58
+ def draw_health(health)
59
+ @font.draw_text("Health: #{health}", 20, @window.height - 70, 0, 1, 1, Gosu::Color::RED)
60
+ end
61
+
62
+ # Draw the armor display
63
+ # @param armor [Integer] the player's armor
64
+ def draw_armor(armor)
65
+ @font.draw_text("Armor: #{armor}", 20, @window.height - 50, 0, 1, 1, Gosu::Color::GREEN)
66
+ end
67
+
68
+ # Draw the ammo display
69
+ # @param ammo [Integer] the player's ammo
70
+ def draw_ammo(ammo)
71
+ @font.draw_text("Ammo: #{ammo}", @window.width - 120, @window.height - 70, 0, 1, 1, Gosu::Color::YELLOW)
72
+ end
73
+
74
+ # Draw the weapon display
75
+ # @param weapon [String] the player's current weapon
76
+ def draw_weapon(weapon)
77
+ @font.draw_text("Weapon: #{weapon}", @window.width - 120, @window.height - 50, 0, 1, 1, Gosu::Color::WHITE)
78
+ end
79
+ end
80
+ end