doom 0.2.0 → 0.4.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 +4 -4
- data/README.md +75 -115
- data/bin/doom +47 -58
- data/lib/doom/game/player_state.rb +221 -0
- data/lib/doom/game/sector_actions.rb +162 -0
- data/lib/doom/map/data.rb +280 -0
- data/lib/doom/platform/gosu_window.rb +414 -0
- data/lib/doom/render/renderer.rb +1272 -0
- data/lib/doom/render/status_bar.rb +166 -0
- data/lib/doom/render/weapon_renderer.rb +102 -0
- data/lib/doom/version.rb +1 -1
- data/lib/doom/wad/colormap.rb +32 -0
- data/lib/doom/wad/flat.rb +40 -0
- data/lib/doom/wad/hud_graphics.rb +189 -0
- data/lib/doom/wad/palette.rb +37 -0
- data/lib/doom/wad/patch.rb +61 -0
- data/lib/doom/wad/reader.rb +79 -0
- data/lib/doom/wad/sprite.rb +205 -0
- data/lib/doom/wad/texture.rb +153 -0
- data/lib/doom/wad_downloader.rb +143 -0
- data/lib/doom.rb +70 -37
- metadata +37 -35
- data/LICENSE.txt +0 -21
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/bin/wad +0 -152
- data/lib/doom/bsp_renderer.rb +0 -90
- data/lib/doom/game.rb +0 -84
- data/lib/doom/hud.rb +0 -80
- data/lib/doom/map_loader.rb +0 -255
- data/lib/doom/renderer.rb +0 -32
- data/lib/doom/sprite_loader.rb +0 -88
- data/lib/doom/sprite_renderer.rb +0 -56
- data/lib/doom/texture_loader.rb +0 -138
- data/lib/doom/texture_mapper.rb +0 -57
- data/lib/doom/wad_loader.rb +0 -106
- data/lib/doom/window.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cb48bcb7558c2e4f4ab959b16dbd857d2a1b6a3b9a9cc76c19a08ec91bdeb93e
|
|
4
|
+
data.tar.gz: 610f42cf954c60048a0c4030d96a8e8ceb2872aba90e90a141b2179329867c05
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ff09fd05c29a5c49b7d41285424d58b8b46dbf995e1f18106d571f18866762e8b20ecb47d472dc2cb2be8f2fc8cdea5eb0b3a2dedae55d5b1881bbcb796088b
|
|
7
|
+
data.tar.gz: 41d4fcb793f3b25fb57f2d50c02f5eee1a56cb40a40baf2a9f7e0831634f43aa4777abf80968130c44593055dbaea23bd3257e7d4b509a068af2c92e1e16698d
|
data/README.md
CHANGED
|
@@ -1,159 +1,119 @@
|
|
|
1
|
-
# Ruby
|
|
1
|
+
# DOOM Ruby
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A faithful ruby port of the DOOM (1993) rendering engine to Ruby.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Features
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
- Pure Ruby implementation of DOOM's BSP rendering engine
|
|
10
|
+
- Accurate wall, floor, and ceiling rendering with proper texture mapping
|
|
11
|
+
- Sprite rendering with depth-correct clipping
|
|
12
|
+
- Original DOOM lighting and colormap support
|
|
13
|
+
- Mouse look and WASD movement controls
|
|
14
|
+
- Supports original WAD files (shareware and registered)
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
## Installation
|
|
14
17
|
|
|
15
18
|
```bash
|
|
16
|
-
|
|
19
|
+
gem install doom
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
Just run `doom` - it will offer to download the free shareware version:
|
|
20
25
|
|
|
21
26
|
```bash
|
|
22
|
-
|
|
27
|
+
doom
|
|
23
28
|
```
|
|
24
29
|
|
|
25
|
-
|
|
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:
|
|
30
|
+
Or specify your own WAD file:
|
|
39
31
|
|
|
40
32
|
```bash
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# List all maps in a WAD file
|
|
45
|
-
$ wad -l DOOM.WAD
|
|
33
|
+
doom /path/to/doom.wad
|
|
34
|
+
```
|
|
46
35
|
|
|
47
|
-
|
|
48
|
-
$ wad -m E1M1 DOOM.WAD
|
|
36
|
+
## Controls
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
| Key | Action |
|
|
39
|
+
|-----|--------|
|
|
40
|
+
| W / Up Arrow | Move forward |
|
|
41
|
+
| S / Down Arrow | Move backward |
|
|
42
|
+
| A | Strafe left |
|
|
43
|
+
| D | Strafe right |
|
|
44
|
+
| Left Arrow | Turn left |
|
|
45
|
+
| Right Arrow | Turn right |
|
|
46
|
+
| Mouse | Look around (click to capture) |
|
|
47
|
+
| Escape | Release mouse / Quit |
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
$ wad -x STARTAN1 DOOM.WAD
|
|
49
|
+
## Requirements
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
- Ruby 3.1 or higher
|
|
52
|
+
- Gosu gem (for window/graphics)
|
|
53
|
+
- SDL2 (native library required by Gosu)
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
$ wad -p TROOA1 DOOM.WAD
|
|
55
|
+
### Installing SDL2
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
**macOS:**
|
|
58
|
+
```bash
|
|
59
|
+
brew install sdl2
|
|
64
60
|
```
|
|
65
61
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
The `doom` command allows you to start the game:
|
|
69
|
-
|
|
62
|
+
**Ubuntu/Debian:**
|
|
70
63
|
```bash
|
|
71
|
-
|
|
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
|
|
64
|
+
sudo apt-get install build-essential libsdl2-dev libgl1-mesa-dev libfontconfig1-dev
|
|
85
65
|
```
|
|
86
66
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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(', ')}"
|
|
67
|
+
**Fedora:**
|
|
68
|
+
```bash
|
|
69
|
+
sudo dnf install SDL2-devel mesa-libGL-devel fontconfig-devel gcc-c++
|
|
117
70
|
```
|
|
118
71
|
|
|
119
|
-
|
|
72
|
+
**Arch Linux:**
|
|
73
|
+
```bash
|
|
74
|
+
sudo pacman -S sdl2 mesa
|
|
75
|
+
```
|
|
120
76
|
|
|
121
|
-
|
|
77
|
+
**Windows:**
|
|
78
|
+
No additional setup needed - the gem includes SDL2.
|
|
122
79
|
|
|
123
|
-
|
|
124
|
-
- Map data extraction
|
|
125
|
-
- Texture information parsing
|
|
126
|
-
- Sprite data handling
|
|
80
|
+
## Development
|
|
127
81
|
|
|
128
|
-
|
|
82
|
+
```bash
|
|
83
|
+
git clone https://github.com/khasinski/doom-rb.git
|
|
84
|
+
cd doom-rb
|
|
85
|
+
bundle install
|
|
86
|
+
ruby bin/doom doom1.wad
|
|
87
|
+
```
|
|
129
88
|
|
|
130
|
-
|
|
131
|
-
- BSP rendering
|
|
132
|
-
- Texture mapping
|
|
133
|
-
- Sprite rendering
|
|
134
|
-
- HUD implementation
|
|
135
|
-
- Basic game loop
|
|
89
|
+
Run specs:
|
|
136
90
|
|
|
137
|
-
|
|
91
|
+
```bash
|
|
92
|
+
bundle exec rspec
|
|
93
|
+
```
|
|
138
94
|
|
|
139
|
-
|
|
140
|
-
- Advanced game loop and state management
|
|
141
|
-
- Polishing
|
|
95
|
+
## Technical Details
|
|
142
96
|
|
|
143
|
-
|
|
97
|
+
This implementation includes:
|
|
144
98
|
|
|
145
|
-
|
|
99
|
+
- **BSP Traversal**: Front-to-back rendering using the map's BSP tree
|
|
100
|
+
- **Visplanes**: Floor/ceiling rendering with R_CheckPlane splitting
|
|
101
|
+
- **Drawsegs**: Wall segment tracking for proper sprite clipping
|
|
102
|
+
- **Texture Mapping**: Perspective-correct texture coordinates
|
|
103
|
+
- **Lighting**: Distance-based light diminishing with colormaps
|
|
146
104
|
|
|
147
|
-
|
|
105
|
+
## Legal
|
|
148
106
|
|
|
149
|
-
|
|
107
|
+
DOOM is a registered trademark of id Software LLC. This is an unofficial fan project.
|
|
150
108
|
|
|
151
|
-
|
|
109
|
+
The shareware version of DOOM (Episode 1) is freely distributable. For the full game,
|
|
110
|
+
please purchase DOOM from [Steam](https://store.steampowered.com/app/2280/Ultimate_Doom/),
|
|
111
|
+
[GOG](https://www.gog.com/pl/game/doom_doom_ii), or other retailers.
|
|
152
112
|
|
|
153
113
|
## License
|
|
154
114
|
|
|
155
|
-
|
|
115
|
+
GPL-2.0 - Same license as the original DOOM source code.
|
|
156
116
|
|
|
157
|
-
##
|
|
117
|
+
## Author
|
|
158
118
|
|
|
159
|
-
|
|
119
|
+
Chris Hasinski ([@khasinski](https://github.com/khasinski))
|
data/bin/doom
CHANGED
|
@@ -1,70 +1,59 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
4
|
+
# Enable YJIT if available (Ruby 3.1+) for better performance
|
|
5
|
+
if defined?(RubyVM::YJIT) && RubyVM::YJIT.respond_to?(:enable)
|
|
6
|
+
RubyVM::YJIT.enable
|
|
38
7
|
end
|
|
39
8
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
9
|
+
# Parse arguments before loading heavy dependencies
|
|
10
|
+
wad_path = ARGV[0]
|
|
11
|
+
|
|
12
|
+
# Show help (before loading anything)
|
|
13
|
+
if wad_path == '-h' || wad_path == '--help'
|
|
14
|
+
puts "DOOM - Ruby port of the classic 1993 game"
|
|
15
|
+
puts
|
|
16
|
+
puts "Usage: doom [OPTIONS] [WAD_FILE]"
|
|
17
|
+
puts
|
|
18
|
+
puts "Options:"
|
|
19
|
+
puts " -h, --help Show this help message"
|
|
20
|
+
puts " -v, --version Show version"
|
|
21
|
+
puts
|
|
22
|
+
puts "If no WAD file is specified, doom will look for doom1.wad in:"
|
|
23
|
+
puts " 1. Current directory"
|
|
24
|
+
puts " 2. ~/.doom/"
|
|
25
|
+
puts
|
|
26
|
+
puts "If not found, you'll be prompted to download the shareware version."
|
|
27
|
+
puts
|
|
28
|
+
puts "Controls:"
|
|
29
|
+
puts " W/Up - Move forward"
|
|
30
|
+
puts " S/Down - Move backward"
|
|
31
|
+
puts " A - Strafe left"
|
|
32
|
+
puts " D - Strafe right"
|
|
33
|
+
puts " Left - Turn left"
|
|
34
|
+
puts " Right - Turn right"
|
|
35
|
+
puts " Mouse - Look around (click to capture)"
|
|
36
|
+
puts " Escape - Release mouse / Quit"
|
|
37
|
+
exit 0
|
|
46
38
|
end
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
puts "
|
|
51
|
-
exit
|
|
40
|
+
if wad_path == '-v' || wad_path == '--version'
|
|
41
|
+
require_relative '../lib/doom/version'
|
|
42
|
+
puts "DOOM Ruby v#{Doom::VERSION}"
|
|
43
|
+
exit 0
|
|
52
44
|
end
|
|
53
45
|
|
|
46
|
+
# Now load the full library
|
|
47
|
+
require_relative '../lib/doom'
|
|
48
|
+
|
|
54
49
|
begin
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
50
|
+
# Find or download WAD
|
|
51
|
+
wad_path = Doom::WadDownloader.ensure_wad_available(wad_path)
|
|
52
|
+
Doom.run(wad_path)
|
|
53
|
+
rescue Doom::WadDownloader::DownloadError => e
|
|
68
54
|
puts "Error: #{e.message}"
|
|
69
55
|
exit 1
|
|
70
|
-
|
|
56
|
+
rescue Interrupt
|
|
57
|
+
puts "\nQuitting..."
|
|
58
|
+
exit 0
|
|
59
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doom
|
|
4
|
+
module Game
|
|
5
|
+
# Tracks player state for HUD display and weapon rendering
|
|
6
|
+
class PlayerState
|
|
7
|
+
# Weapons
|
|
8
|
+
WEAPON_FIST = 0
|
|
9
|
+
WEAPON_PISTOL = 1
|
|
10
|
+
WEAPON_SHOTGUN = 2
|
|
11
|
+
WEAPON_CHAINGUN = 3
|
|
12
|
+
WEAPON_ROCKET = 4
|
|
13
|
+
WEAPON_PLASMA = 5
|
|
14
|
+
WEAPON_BFG = 6
|
|
15
|
+
WEAPON_CHAINSAW = 7
|
|
16
|
+
|
|
17
|
+
# Weapon symbols for graphics lookup
|
|
18
|
+
WEAPON_NAMES = {
|
|
19
|
+
WEAPON_FIST => :fist,
|
|
20
|
+
WEAPON_PISTOL => :pistol,
|
|
21
|
+
WEAPON_SHOTGUN => :shotgun,
|
|
22
|
+
WEAPON_CHAINGUN => :chaingun,
|
|
23
|
+
WEAPON_ROCKET => :rocket,
|
|
24
|
+
WEAPON_PLASMA => :plasma,
|
|
25
|
+
WEAPON_BFG => :bfg,
|
|
26
|
+
WEAPON_CHAINSAW => :chainsaw
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
# Attack durations (in frames at 35fps)
|
|
30
|
+
ATTACK_DURATIONS = {
|
|
31
|
+
WEAPON_FIST => 12,
|
|
32
|
+
WEAPON_PISTOL => 8,
|
|
33
|
+
WEAPON_SHOTGUN => 20,
|
|
34
|
+
WEAPON_CHAINGUN => 4,
|
|
35
|
+
WEAPON_ROCKET => 16,
|
|
36
|
+
WEAPON_PLASMA => 6,
|
|
37
|
+
WEAPON_BFG => 40,
|
|
38
|
+
WEAPON_CHAINSAW => 4
|
|
39
|
+
}.freeze
|
|
40
|
+
|
|
41
|
+
attr_accessor :health, :armor, :max_health, :max_armor
|
|
42
|
+
attr_accessor :ammo_bullets, :ammo_shells, :ammo_rockets, :ammo_cells
|
|
43
|
+
attr_accessor :max_bullets, :max_shells, :max_rockets, :max_cells
|
|
44
|
+
attr_accessor :weapon, :has_weapons
|
|
45
|
+
attr_accessor :keys
|
|
46
|
+
attr_accessor :attacking, :attack_frame, :attack_tics
|
|
47
|
+
attr_accessor :bob_angle, :bob_amount
|
|
48
|
+
attr_accessor :is_moving
|
|
49
|
+
|
|
50
|
+
def initialize
|
|
51
|
+
reset
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def reset
|
|
55
|
+
@health = 100
|
|
56
|
+
@armor = 0
|
|
57
|
+
@max_health = 100
|
|
58
|
+
@max_armor = 200
|
|
59
|
+
|
|
60
|
+
# Ammo
|
|
61
|
+
@ammo_bullets = 50
|
|
62
|
+
@ammo_shells = 0
|
|
63
|
+
@ammo_rockets = 0
|
|
64
|
+
@ammo_cells = 0
|
|
65
|
+
|
|
66
|
+
@max_bullets = 200
|
|
67
|
+
@max_shells = 50
|
|
68
|
+
@max_rockets = 50
|
|
69
|
+
@max_cells = 300
|
|
70
|
+
|
|
71
|
+
# Start with fist and pistol
|
|
72
|
+
@weapon = WEAPON_PISTOL
|
|
73
|
+
@has_weapons = [true, true, false, false, false, false, false, false]
|
|
74
|
+
|
|
75
|
+
# No keys
|
|
76
|
+
@keys = {
|
|
77
|
+
blue_card: false,
|
|
78
|
+
yellow_card: false,
|
|
79
|
+
red_card: false,
|
|
80
|
+
blue_skull: false,
|
|
81
|
+
yellow_skull: false,
|
|
82
|
+
red_skull: false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Attack state
|
|
86
|
+
@attacking = false
|
|
87
|
+
@attack_frame = 0
|
|
88
|
+
@attack_tics = 0
|
|
89
|
+
|
|
90
|
+
# Weapon bob
|
|
91
|
+
@bob_angle = 0.0
|
|
92
|
+
@bob_amount = 0.0
|
|
93
|
+
@is_moving = false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def weapon_name
|
|
97
|
+
WEAPON_NAMES[@weapon]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def current_ammo
|
|
101
|
+
case @weapon
|
|
102
|
+
when WEAPON_PISTOL, WEAPON_CHAINGUN
|
|
103
|
+
@ammo_bullets
|
|
104
|
+
when WEAPON_SHOTGUN
|
|
105
|
+
@ammo_shells
|
|
106
|
+
when WEAPON_ROCKET
|
|
107
|
+
@ammo_rockets
|
|
108
|
+
when WEAPON_PLASMA, WEAPON_BFG
|
|
109
|
+
@ammo_cells
|
|
110
|
+
else
|
|
111
|
+
nil # Fist/chainsaw don't use ammo
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def max_ammo_for_weapon
|
|
116
|
+
case @weapon
|
|
117
|
+
when WEAPON_PISTOL, WEAPON_CHAINGUN
|
|
118
|
+
@max_bullets
|
|
119
|
+
when WEAPON_SHOTGUN
|
|
120
|
+
@max_shells
|
|
121
|
+
when WEAPON_ROCKET
|
|
122
|
+
@max_rockets
|
|
123
|
+
when WEAPON_PLASMA, WEAPON_BFG
|
|
124
|
+
@max_cells
|
|
125
|
+
else
|
|
126
|
+
nil
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def can_attack?
|
|
131
|
+
return true if @weapon == WEAPON_FIST || @weapon == WEAPON_CHAINSAW
|
|
132
|
+
|
|
133
|
+
ammo = current_ammo
|
|
134
|
+
ammo && ammo > 0
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def start_attack
|
|
138
|
+
return unless can_attack?
|
|
139
|
+
return if @attacking
|
|
140
|
+
|
|
141
|
+
@attacking = true
|
|
142
|
+
@attack_frame = 0
|
|
143
|
+
@attack_tics = 0
|
|
144
|
+
|
|
145
|
+
# Consume ammo
|
|
146
|
+
case @weapon
|
|
147
|
+
when WEAPON_PISTOL
|
|
148
|
+
@ammo_bullets -= 1 if @ammo_bullets > 0
|
|
149
|
+
when WEAPON_SHOTGUN
|
|
150
|
+
@ammo_shells -= 1 if @ammo_shells > 0
|
|
151
|
+
when WEAPON_CHAINGUN
|
|
152
|
+
@ammo_bullets -= 1 if @ammo_bullets > 0
|
|
153
|
+
when WEAPON_ROCKET
|
|
154
|
+
@ammo_rockets -= 1 if @ammo_rockets > 0
|
|
155
|
+
when WEAPON_PLASMA
|
|
156
|
+
@ammo_cells -= 1 if @ammo_cells > 0
|
|
157
|
+
when WEAPON_BFG
|
|
158
|
+
@ammo_cells -= 40 if @ammo_cells >= 40
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def update_attack
|
|
163
|
+
return unless @attacking
|
|
164
|
+
|
|
165
|
+
@attack_tics += 1
|
|
166
|
+
|
|
167
|
+
# Calculate which frame we're on based on tics
|
|
168
|
+
duration = ATTACK_DURATIONS[@weapon] || 8
|
|
169
|
+
frame_count = @weapon == WEAPON_FIST ? 3 : 4
|
|
170
|
+
|
|
171
|
+
tics_per_frame = duration / frame_count
|
|
172
|
+
@attack_frame = (@attack_tics / tics_per_frame).to_i
|
|
173
|
+
|
|
174
|
+
# Attack finished?
|
|
175
|
+
if @attack_tics >= duration
|
|
176
|
+
@attacking = false
|
|
177
|
+
@attack_frame = 0
|
|
178
|
+
@attack_tics = 0
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def update_bob(delta_time)
|
|
183
|
+
if @is_moving
|
|
184
|
+
# Increase bob while moving
|
|
185
|
+
@bob_angle += delta_time * 10.0
|
|
186
|
+
@bob_amount = [@bob_amount + delta_time * 16.0, 6.0].min
|
|
187
|
+
else
|
|
188
|
+
# Decay bob when stopped
|
|
189
|
+
@bob_amount = [@bob_amount - delta_time * 12.0, 0.0].max
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def weapon_bob_x
|
|
194
|
+
Math.cos(@bob_angle) * @bob_amount
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def weapon_bob_y
|
|
198
|
+
Math.sin(@bob_angle * 2) * @bob_amount * 0.5
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def health_level
|
|
202
|
+
# 0 = dying, 4 = full health
|
|
203
|
+
case @health
|
|
204
|
+
when 80..200 then 4
|
|
205
|
+
when 60..79 then 3
|
|
206
|
+
when 40..59 then 2
|
|
207
|
+
when 20..39 then 1
|
|
208
|
+
else 0
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def switch_weapon(weapon_num)
|
|
213
|
+
return unless weapon_num >= 0 && weapon_num < 8
|
|
214
|
+
return unless @has_weapons[weapon_num]
|
|
215
|
+
return if @attacking
|
|
216
|
+
|
|
217
|
+
@weapon = weapon_num
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|