doom 0.2.0 → 0.3.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.
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'fileutils'
6
+
7
+ module Doom
8
+ # Downloads the shareware DOOM1.WAD if not present
9
+ class WadDownloader
10
+ # Official Doom shareware WAD, uploaded by id Software to archive.org
11
+ SHAREWARE_URL = 'https://archive.org/download/doom-shareware_1996/DOOM1.WAD'
12
+ SHAREWARE_SIZE = 4_196_020 # Expected size in bytes
13
+ SHAREWARE_FILENAME = 'doom1.wad'
14
+
15
+ class DownloadError < StandardError; end
16
+
17
+ def self.ensure_wad_available(custom_path = nil)
18
+ # If custom path provided and exists, use it
19
+ return custom_path if custom_path && File.exist?(custom_path)
20
+
21
+ # Check current directory for doom1.wad
22
+ local_wad = File.join(Dir.pwd, SHAREWARE_FILENAME)
23
+ return local_wad if File.exist?(local_wad)
24
+
25
+ # Check home directory .doom folder
26
+ home_wad = File.join(Dir.home, '.doom', SHAREWARE_FILENAME)
27
+ return home_wad if File.exist?(home_wad)
28
+
29
+ # No WAD found - offer to download
30
+ if custom_path
31
+ raise DownloadError, "WAD file not found: #{custom_path}"
32
+ end
33
+
34
+ prompt_and_download(home_wad)
35
+ end
36
+
37
+ def self.prompt_and_download(destination)
38
+ puts "No DOOM WAD file found."
39
+ puts
40
+ puts "Would you like to download the shareware version of DOOM (4 MB)?"
41
+ puts "This is the free, legally distributable version with Episode 1."
42
+ puts
43
+ print "Download shareware DOOM? [Y/n] "
44
+
45
+ response = $stdin.gets&.strip&.downcase
46
+ if response.nil? || response.empty? || response == 'y' || response == 'yes'
47
+ download_shareware(destination)
48
+ destination
49
+ else
50
+ puts
51
+ puts "To play DOOM, you need a WAD file. Options:"
52
+ puts " 1. Run 'doom' again and accept the shareware download"
53
+ puts " 2. Copy your own doom1.wad or doom.wad to the current directory"
54
+ puts " 3. Specify a WAD path: doom /path/to/your.wad"
55
+ exit 1
56
+ end
57
+ end
58
+
59
+ def self.download_shareware(destination)
60
+ puts
61
+ puts "Downloading DOOM shareware..."
62
+
63
+ # Create directory if needed
64
+ FileUtils.mkdir_p(File.dirname(destination))
65
+
66
+ uri = URI.parse(SHAREWARE_URL)
67
+ downloaded = 0
68
+
69
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
70
+ request = Net::HTTP::Get.new(uri)
71
+
72
+ http.request(request) do |response|
73
+ case response
74
+ when Net::HTTPRedirection
75
+ # Follow redirect
76
+ return download_from_url(response['location'], destination)
77
+ when Net::HTTPSuccess
78
+ total_size = response['content-length']&.to_i || SHAREWARE_SIZE
79
+
80
+ File.open(destination, 'wb') do |file|
81
+ response.read_body do |chunk|
82
+ file.write(chunk)
83
+ downloaded += chunk.size
84
+ print_progress(downloaded, total_size)
85
+ end
86
+ end
87
+ else
88
+ raise DownloadError, "Download failed: #{response.code} #{response.message}"
89
+ end
90
+ end
91
+ end
92
+
93
+ puts
94
+ puts "Downloaded to: #{destination}"
95
+ puts
96
+
97
+ # Verify file size
98
+ actual_size = File.size(destination)
99
+ if actual_size < 1_000_000 # Less than 1MB is suspicious
100
+ File.delete(destination)
101
+ raise DownloadError, "Download appears incomplete (#{actual_size} bytes)"
102
+ end
103
+ end
104
+
105
+ def self.download_from_url(url, destination)
106
+ uri = URI.parse(url)
107
+ downloaded = 0
108
+
109
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
110
+ request = Net::HTTP::Get.new(uri)
111
+
112
+ http.request(request) do |response|
113
+ case response
114
+ when Net::HTTPRedirection
115
+ return download_from_url(response['location'], destination)
116
+ when Net::HTTPSuccess
117
+ total_size = response['content-length']&.to_i || SHAREWARE_SIZE
118
+
119
+ File.open(destination, 'wb') do |file|
120
+ response.read_body do |chunk|
121
+ file.write(chunk)
122
+ downloaded += chunk.size
123
+ print_progress(downloaded, total_size)
124
+ end
125
+ end
126
+ else
127
+ raise DownloadError, "Download failed: #{response.code} #{response.message}"
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ def self.print_progress(downloaded, total)
134
+ percent = (downloaded.to_f / total * 100).to_i
135
+ bar_width = 40
136
+ filled = (percent * bar_width / 100)
137
+ bar = '=' * filled + '-' * (bar_width - filled)
138
+ mb_downloaded = (downloaded / 1_048_576.0).round(1)
139
+ mb_total = (total / 1_048_576.0).round(1)
140
+ print "\r[#{bar}] #{percent}% (#{mb_downloaded}/#{mb_total} MB)"
141
+ end
142
+ end
143
+ end
data/lib/doom.rb CHANGED
@@ -1,46 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "doom/version"
4
- require_relative "doom/wad_loader"
5
- require_relative "doom/map_loader"
6
- require_relative "doom/texture_loader"
7
- require_relative "doom/sprite_loader"
8
- require_relative "doom/window"
9
- require_relative "doom/renderer"
10
- require_relative "doom/bsp_renderer"
11
- require_relative "doom/texture_mapper"
12
- require_relative "doom/sprite_renderer"
13
- require_relative "doom/hud"
14
- require_relative "doom/game"
3
+ require_relative 'doom/version'
4
+ require_relative 'doom/wad_downloader'
5
+ require_relative 'doom/wad/reader'
6
+ require_relative 'doom/wad/palette'
7
+ require_relative 'doom/wad/colormap'
8
+ require_relative 'doom/wad/flat'
9
+ require_relative 'doom/wad/patch'
10
+ require_relative 'doom/wad/texture'
11
+ require_relative 'doom/wad/sprite'
12
+ require_relative 'doom/map/data'
13
+ require_relative 'doom/render/renderer'
14
+ require_relative 'doom/platform/gosu_window'
15
15
 
16
16
  module Doom
17
17
  class Error < StandardError; end
18
18
 
19
- # Load a WAD file and return loaders for its components
20
- # @param filename [String] path to the WAD file
21
- # @return [Hash] hash containing the various loaders
22
- def self.load_wad(filename)
23
- wad_loader = WADLoader.new(filename)
24
- map_loader = MapLoader.new(wad_loader)
25
- texture_loader = TextureLoader.new(wad_loader)
26
- sprite_loader = SpriteLoader.new(wad_loader)
27
-
28
- {
29
- wad: wad_loader,
30
- maps: map_loader,
31
- textures: texture_loader,
32
- sprites: sprite_loader
33
- }
34
- end
19
+ class << self
20
+ def run(wad_path, map_name: 'E1M1')
21
+ puts "Loading WAD: #{wad_path}"
22
+ wad = Wad::Reader.new(wad_path)
23
+ puts " #{wad.type}: #{wad.num_lumps} lumps"
24
+
25
+ puts 'Loading palette...'
26
+ palette = Wad::Palette.load(wad)
27
+
28
+ puts 'Loading colormap...'
29
+ colormap = Wad::Colormap.load(wad)
30
+
31
+ puts 'Loading flats...'
32
+ flats = Wad::Flat.load_all(wad)
33
+ puts " #{flats.size} flats"
34
+
35
+ puts 'Loading textures...'
36
+ textures = Wad::TextureManager.new(wad)
37
+ puts " #{textures.textures.size} textures, #{textures.pnames.size} patches"
38
+
39
+ puts 'Loading sprites...'
40
+ sprites = Wad::SpriteManager.new(wad)
41
+
42
+ puts "Loading map #{map_name}..."
43
+ map = Map::MapData.load(wad, map_name)
44
+ puts " #{map.vertices.size} vertices, #{map.linedefs.size} linedefs"
45
+ puts " #{map.segs.size} segs, #{map.subsectors.size} subsectors, #{map.nodes.size} nodes"
46
+
47
+ # Find player start
48
+ player_start = map.player_start
49
+ if player_start
50
+ puts " Player start: (#{player_start.x}, #{player_start.y}) angle #{player_start.angle}"
51
+ else
52
+ puts ' Warning: No player start found!'
53
+ player_start = Map::Thing.new(0, 0, 90, 1, 0)
54
+ end
55
+
56
+ puts 'Creating renderer...'
57
+ renderer = Render::Renderer.new(wad, map, textures, palette, colormap, flats, sprites)
58
+ renderer.set_player(player_start.x, player_start.y, 41, player_start.angle)
35
59
 
36
- # Start the game with the given WAD file
37
- # @param wad_file [String] path to the WAD file
38
- # @param map_name [String] name of the map to start on (optional)
39
- # @param width [Integer] width of the window (default: 640)
40
- # @param height [Integer] height of the window (default: 480)
41
- # @param fullscreen [Boolean] whether to start in fullscreen mode (default: false)
42
- def self.start_game(wad_file, map_name = nil, width = 640, height = 480, fullscreen = false)
43
- game = Game.new(wad_file, width, height, fullscreen)
44
- game.start(map_name)
60
+ puts 'Starting game window...'
61
+ window = Platform::GosuWindow.new(renderer, palette, map)
62
+ window.show
63
+ end
45
64
  end
46
65
  end
metadata CHANGED
@@ -1,57 +1,59 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Hasinski
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2025-12-21 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
- name: rake
14
+ name: gosu
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
17
  - - "~>"
17
18
  - !ruby/object:Gem::Version
18
- version: '13.0'
19
- type: :development
19
+ version: '1.4'
20
+ type: :runtime
20
21
  prerelease: false
21
22
  version_requirements: !ruby/object:Gem::Requirement
22
23
  requirements:
23
24
  - - "~>"
24
25
  - !ruby/object:Gem::Version
25
- version: '13.0'
26
+ version: '1.4'
26
27
  - !ruby/object:Gem::Dependency
27
- name: minitest
28
+ name: rspec
28
29
  requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - "~>"
31
32
  - !ruby/object:Gem::Version
32
- version: '5.0'
33
+ version: '3.12'
33
34
  type: :development
34
35
  prerelease: false
35
36
  version_requirements: !ruby/object:Gem::Requirement
36
37
  requirements:
37
38
  - - "~>"
38
39
  - !ruby/object:Gem::Version
39
- version: '5.0'
40
+ version: '3.12'
40
41
  - !ruby/object:Gem::Dependency
41
- name: gosu
42
+ name: chunky_png
42
43
  requirement: !ruby/object:Gem::Requirement
43
44
  requirements:
44
45
  - - "~>"
45
46
  - !ruby/object:Gem::Version
46
47
  version: '1.4'
47
- type: :runtime
48
+ type: :development
48
49
  prerelease: false
49
50
  version_requirements: !ruby/object:Gem::Requirement
50
51
  requirements:
51
52
  - - "~>"
52
53
  - !ruby/object:Gem::Version
53
54
  version: '1.4'
54
- description: Ruby Doom is a Ruby gem that ports the classic Doom game to Ruby
55
+ description: A faithful port of the Doom (1993) rendering engine to Ruby. Supports
56
+ original WAD files with near pixel-perfect BSP rendering.
55
57
  email:
56
58
  - krzysztof.hasinski@gmail.com
57
59
  executables:
@@ -59,32 +61,26 @@ executables:
59
61
  extensions: []
60
62
  extra_rdoc_files: []
61
63
  files:
62
- - LICENSE.txt
63
64
  - README.md
64
- - bin/console
65
65
  - bin/doom
66
- - bin/setup
67
- - bin/wad
68
66
  - lib/doom.rb
69
- - lib/doom/bsp_renderer.rb
70
- - lib/doom/game.rb
71
- - lib/doom/hud.rb
72
- - lib/doom/map_loader.rb
73
- - lib/doom/renderer.rb
74
- - lib/doom/sprite_loader.rb
75
- - lib/doom/sprite_renderer.rb
76
- - lib/doom/texture_loader.rb
77
- - lib/doom/texture_mapper.rb
67
+ - lib/doom/map/data.rb
68
+ - lib/doom/platform/gosu_window.rb
69
+ - lib/doom/render/renderer.rb
78
70
  - lib/doom/version.rb
79
- - lib/doom/wad_loader.rb
80
- - lib/doom/window.rb
71
+ - lib/doom/wad/colormap.rb
72
+ - lib/doom/wad/flat.rb
73
+ - lib/doom/wad/palette.rb
74
+ - lib/doom/wad/patch.rb
75
+ - lib/doom/wad/reader.rb
76
+ - lib/doom/wad/sprite.rb
77
+ - lib/doom/wad/texture.rb
78
+ - lib/doom/wad_downloader.rb
81
79
  homepage: https://github.com/khasinski/doom-rb
82
80
  licenses:
83
- - MIT
84
- metadata:
85
- homepage_uri: https://github.com/khasinski/doom-rb
86
- source_code_uri: https://github.com/khasinski/doom-rb
87
- changelog_uri: https://github.com/khasinski/doom-rb/blob/master/CHANGELOG.md
81
+ - GPL-2.0
82
+ metadata: {}
83
+ post_install_message:
88
84
  rdoc_options: []
89
85
  require_paths:
90
86
  - lib
@@ -92,14 +88,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
88
  requirements:
93
89
  - - ">="
94
90
  - !ruby/object:Gem::Version
95
- version: 2.6.0
91
+ version: '3.1'
96
92
  required_rubygems_version: !ruby/object:Gem::Requirement
97
93
  requirements:
98
94
  - - ">="
99
95
  - !ruby/object:Gem::Version
100
96
  version: '0'
101
97
  requirements: []
102
- rubygems_version: 3.6.8
98
+ rubygems_version: 3.5.22
99
+ signing_key:
103
100
  specification_version: 4
104
- summary: A Ruby port of the classic Doom game
101
+ summary: Doom engine port in pure Ruby
105
102
  test_files: []
data/LICENSE.txt DELETED
@@ -1,21 +0,0 @@
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/bin/console DELETED
@@ -1,15 +0,0 @@
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/setup DELETED
@@ -1,8 +0,0 @@
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 DELETED
@@ -1,152 +0,0 @@
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
@@ -1,90 +0,0 @@
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