ruby_rpg 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/{lib → bin}/build.bash +4 -3
- data/lib/engine/autoloader.rb +11 -0
- data/lib/engine/component.rb +16 -1
- data/lib/engine/components/audio_source.rb +41 -0
- data/lib/engine/components/orthographic_camera.rb +2 -2
- data/lib/engine/debugging.rb +41 -0
- data/lib/engine/engine.rb +15 -105
- data/lib/engine/font.rb +2 -2
- data/lib/engine/game_object.rb +45 -9
- data/lib/engine/input.rb +44 -1
- data/lib/engine/mesh.rb +2 -2
- data/lib/engine/quaternion.rb +6 -0
- data/lib/engine/texture.rb +3 -2
- data/lib/ruby_rpg.rb +53 -0
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73ebf7bd3a497f3da5bb8bf0c953da36446ef912edede3605ae811a7d7778c21
|
4
|
+
data.tar.gz: 2c6d68447ef0502ca2d19020659bf09b1821fec4ff741ee5901a142358513701
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc07ac48782722967f54d33c0aa633891f1f585557b6cb9427cf0d4ae711b5869c318631f17fd90ef5e82fbdfcf6946542e8cf0874b438aa2165818f601bb20d
|
7
|
+
data.tar.gz: da7fb040ce08572ff69666fe850a3d2bc6d0dd326b040e1c8772f2c4891cef54550baf18d2c558e29b1e9b5ed983a0b016eea6d5345137faaf878bcbbe28d350
|
data/README.md
CHANGED
@@ -5,10 +5,12 @@ It is designed to be easy to use and easy to extend.
|
|
5
5
|
It is still in the early stages of development, but it is already capable of rendering both 2D and 3D graphics.
|
6
6
|
|
7
7
|
## Installation
|
8
|
-
|
8
|
+
You can find full instructions on th [wiki](https://github.com/rubyrpg/ruby_rpg/wiki/Installation).
|
9
9
|
|
10
10
|
## Usage
|
11
|
-
|
11
|
+
You can find docs and guides on the [wiki](https://github.com/rubyrpg/ruby_rpg/wiki).
|
12
|
+
For a basic example to get you up off the ground take a look at [hello_ruby_rpg](https://github.com/rubyrpg/hello_ruby_rpg).
|
13
|
+
For some more complex examples you can take a look in the samples folder of this repo.
|
12
14
|
|
13
15
|
## Contributing
|
14
16
|
1. Fork it
|
data/{lib → bin}/build.bash
RENAMED
@@ -5,8 +5,9 @@ output_file=$2
|
|
5
5
|
|
6
6
|
export BUILDING=true
|
7
7
|
|
8
|
+
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
|
9
|
+
glfw_path=$parent_path/../glfw-3.4.bin.WIN64
|
10
|
+
|
8
11
|
ocran $input_file \
|
9
|
-
**/*.png **/*.obj **/*.glsl **/*.vertex_data **/*.index_data **/*.json **/*.csv
|
12
|
+
**/*.png **/*.obj **/*.glsl **/*.vertex_data **/*.index_data **/*.json **/*.csv $glfw_path/**/* src/**/*.rb \
|
10
13
|
--output $output_file
|
11
|
-
|
12
|
-
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Engine
|
4
|
+
module AutoLoader
|
5
|
+
def self.load(load_path = nil)
|
6
|
+
base_dir = File.expand_path(load_path || File.dirname($PROGRAM_NAME))
|
7
|
+
Dir[File.join(base_dir, "components", "**/*.rb")].each { |file| require file }
|
8
|
+
Dir[File.join(base_dir, "game_objects", "**/*.rb")].each { |file| require file }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/engine/component.rb
CHANGED
@@ -30,8 +30,12 @@ module Engine
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def destroy!
|
33
|
+
Component.destroyed_components << self unless @destroyed
|
34
|
+
destroy unless @destroyed
|
33
35
|
@destroyed = true
|
34
|
-
|
36
|
+
end
|
37
|
+
|
38
|
+
def _erase!
|
35
39
|
game_object.components.delete(self)
|
36
40
|
class_name = self.class.name.split('::').last
|
37
41
|
self.class.instance_variable_get(:@methods).each do |method|
|
@@ -42,7 +46,18 @@ module Engine
|
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
49
|
+
def self.erase_destroyed_components
|
50
|
+
destroyed_components.each do |object|
|
51
|
+
object._erase!
|
52
|
+
end
|
53
|
+
@destroyed_components = []
|
54
|
+
end
|
55
|
+
|
45
56
|
def destroy
|
46
57
|
end
|
58
|
+
|
59
|
+
def self.destroyed_components
|
60
|
+
@destroyed_components ||= []
|
61
|
+
end
|
47
62
|
end
|
48
63
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Engine::Components
|
4
|
+
class AudioSource < Engine::Component
|
5
|
+
def initialize(clip, radius: 1000)
|
6
|
+
@clip = clip
|
7
|
+
@radius = radius
|
8
|
+
@source = NativeAudio::AudioSource.new(clip)
|
9
|
+
end
|
10
|
+
|
11
|
+
def play
|
12
|
+
@source.play
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop
|
16
|
+
@source.stop
|
17
|
+
end
|
18
|
+
|
19
|
+
def pause
|
20
|
+
@source.pause
|
21
|
+
end
|
22
|
+
|
23
|
+
def resume
|
24
|
+
@source.resume
|
25
|
+
end
|
26
|
+
|
27
|
+
def volume=(volume)
|
28
|
+
@source.set_volume(volume)
|
29
|
+
end
|
30
|
+
|
31
|
+
def update(delta_time)
|
32
|
+
camera = Engine::Camera.instance
|
33
|
+
local_pos = camera.game_object.world_to_local_coordinate(game_object.pos)
|
34
|
+
angle = Math.atan2(local_pos[0], -local_pos[2]) * 180 / Math::PI
|
35
|
+
angle = (angle + 360) % 360
|
36
|
+
distance = (local_pos.magnitude * 255 / @radius).clamp(0, 255)
|
37
|
+
|
38
|
+
@source.set_pos(angle, distance)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -33,8 +33,8 @@ module Engine::Components
|
|
33
33
|
@right = nil if game_object.rotation != @rotation
|
34
34
|
@up = nil if game_object.rotation != @rotation
|
35
35
|
@front = nil if game_object.rotation != @rotation
|
36
|
-
@matrix = nil if game_object.rotation.
|
37
|
-
@rotation = game_object.rotation.
|
36
|
+
@matrix = nil if game_object.rotation.dup != @rotation
|
37
|
+
@rotation = game_object.rotation.dup
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Engine
|
4
|
+
module Debugging
|
5
|
+
|
6
|
+
# Hit a breakpoint within the context of where the breakpoint is defined, assuming a block is passed
|
7
|
+
# with a `binding.pry` (or an alternative debugger), otherwise hit a breakpoint within this method.
|
8
|
+
def self.breakpoint(&block)
|
9
|
+
orig_fullscreen = Window.full_screen?
|
10
|
+
if orig_fullscreen
|
11
|
+
Window.set_to_windowed
|
12
|
+
GLFW.PollEvents # Required to trigger the switch from fullscreen to windowed within this breakpoint
|
13
|
+
end
|
14
|
+
|
15
|
+
orig_cursor_mode = Cursor.get_input_mode
|
16
|
+
Cursor.enable
|
17
|
+
|
18
|
+
block_given? ? yield : binding.pry
|
19
|
+
Cursor.restore_input_mode(orig_cursor_mode)
|
20
|
+
Window.set_to_full_screen if orig_fullscreen
|
21
|
+
Window.focus_window
|
22
|
+
|
23
|
+
# Reset the time, otherwise delta_time will be off for the next frame, and teleporting occurs
|
24
|
+
@time = Time.now
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.debug_opengl_call
|
28
|
+
errors = []
|
29
|
+
until GL.GetError == 0; end
|
30
|
+
yield
|
31
|
+
until (error = GL.GetError) == 0
|
32
|
+
errors += error.to_s(16)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.print_opengl_version
|
37
|
+
puts "OpenGL Version: #{GL.GetString(GL::VERSION)}"
|
38
|
+
puts "GLSL Version: #{GL.GetString(GL::SHADING_LANGUAGE_VERSION)}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/engine/engine.rb
CHANGED
@@ -1,55 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require 'os'
|
5
|
-
|
6
|
-
require_relative 'rendering/render_pipeline'
|
7
|
-
require_relative 'rendering/instance_renderer'
|
8
|
-
require_relative 'screenshoter'
|
9
|
-
require_relative 'input'
|
10
|
-
require_relative "quaternion"
|
11
|
-
require_relative 'game_object'
|
12
|
-
require_relative 'texture'
|
13
|
-
require_relative 'material'
|
14
|
-
require_relative 'mesh'
|
15
|
-
require_relative "font"
|
16
|
-
require_relative 'path'
|
17
|
-
require_relative 'polygon_mesh'
|
18
|
-
require_relative 'importers/obj_file'
|
19
|
-
require_relative 'tangent_calculator'
|
20
|
-
require_relative 'shader'
|
21
|
-
require_relative 'component'
|
22
|
-
require_relative "camera"
|
23
|
-
require_relative "window"
|
24
|
-
require_relative "video_mode"
|
25
|
-
require_relative "cursor"
|
26
|
-
|
27
|
-
require_relative "components/orthographic_camera"
|
28
|
-
require_relative "components/perspective_camera"
|
29
|
-
require_relative "components/sprite_renderer"
|
30
|
-
require_relative "components/ui_sprite_renderer"
|
31
|
-
require_relative "components/mesh_renderer"
|
32
|
-
require_relative "components/font_renderer"
|
33
|
-
require_relative "components/ui_font_renderer"
|
34
|
-
require_relative "components/point_light"
|
35
|
-
require_relative "components/direction_light"
|
36
|
-
|
37
|
-
require_relative "physics/physics_resolver"
|
38
|
-
require_relative 'physics/collision'
|
39
|
-
require_relative "physics/components/sphere_collider"
|
40
|
-
require_relative "physics/components/cube_collider"
|
41
|
-
require_relative "physics/components/rigidbody"
|
42
|
-
|
43
|
-
if OS.windows?
|
44
|
-
GLFW.load_lib(File.expand_path(File.join(__dir__, "..", "..", "glfw-3.4.bin.WIN64", "lib-static-ucrt", "glfw3.dll")))
|
45
|
-
elsif OS.mac?
|
46
|
-
GLFW.load_lib(File.expand_path(File.join(__dir__, "..", "..", "glfw-3.3.9.bin.MACOS", "lib-arm64", "libglfw.3.dylib")))
|
47
|
-
end
|
48
|
-
GLFW.Init
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
GAME_DIR = File.expand_path(File.dirname($PROGRAM_NAME))
|
49
4
|
|
50
5
|
module Engine
|
51
|
-
def self.start(
|
52
|
-
load
|
6
|
+
def self.start(&first_frame_block)
|
7
|
+
Engine::AutoLoader.load
|
53
8
|
return if ENV["BUILDING"] == "true"
|
54
9
|
|
55
10
|
open_window
|
@@ -61,20 +16,14 @@ module Engine
|
|
61
16
|
@engine_started
|
62
17
|
end
|
63
18
|
|
64
|
-
def self.load(base_dir)
|
65
|
-
base_dir = File.expand_path(base_dir)
|
66
|
-
Dir[File.join(base_dir, "components", "**/*.rb")].each { |file| require file }
|
67
|
-
Dir[File.join(base_dir, "game_objects", "**/*.rb")].each { |file| require file }
|
68
|
-
end
|
69
|
-
|
70
19
|
def self.open_window
|
71
20
|
@old_time = Time.now
|
72
21
|
@time = Time.now
|
73
|
-
@key_callback = create_key_callbacks # This must be an instance variable to prevent garbage collection
|
74
22
|
|
75
23
|
Window.create_window
|
76
24
|
GLFW.MakeContextCurrent(Window.window)
|
77
|
-
|
25
|
+
|
26
|
+
Input.init
|
78
27
|
GL.load_lib
|
79
28
|
|
80
29
|
set_opengl_blend_mode
|
@@ -85,8 +34,6 @@ module Engine
|
|
85
34
|
GL.CullFace(GL::BACK)
|
86
35
|
|
87
36
|
GLFW.SwapInterval(0)
|
88
|
-
|
89
|
-
Cursor.hide
|
90
37
|
end
|
91
38
|
|
92
39
|
def self.main_game_loop(&first_frame_block)
|
@@ -144,13 +91,10 @@ module Engine
|
|
144
91
|
@fps
|
145
92
|
end
|
146
93
|
|
147
|
-
def self.terminate
|
148
|
-
GLFW.DestroyWindow(Window.window)
|
149
|
-
GLFW.Terminate
|
150
|
-
end
|
151
|
-
|
152
94
|
def self.close
|
153
95
|
GameObject.destroy_all
|
96
|
+
Component.erase_destroyed_components
|
97
|
+
GameObject.erase_destroyed_objects
|
154
98
|
GLFW.SetWindowShouldClose(Window.window, 1)
|
155
99
|
end
|
156
100
|
|
@@ -158,31 +102,17 @@ module Engine
|
|
158
102
|
@game_stopped = true
|
159
103
|
@swap_buffers_promise.wait! if @swap_buffers_promise && !@swap_buffers_promise.complete?
|
160
104
|
GameObject.destroy_all
|
105
|
+
Component.erase_destroyed_components
|
106
|
+
GameObject.erase_destroyed_objects
|
161
107
|
end
|
162
108
|
|
163
|
-
|
164
|
-
# with a `binding.pry` (or an alternative debugger), otherwise hit a breakpoint within this method.
|
165
|
-
def self.breakpoint(&block)
|
166
|
-
orig_fullscreen = Window.full_screen?
|
167
|
-
if orig_fullscreen
|
168
|
-
Window.set_to_windowed
|
169
|
-
GLFW.PollEvents # Required to trigger the switch from fullscreen to windowed within this breakpoint
|
170
|
-
end
|
171
|
-
|
172
|
-
orig_cursor_mode = Cursor.get_input_mode
|
173
|
-
Cursor.enable
|
174
|
-
|
175
|
-
block_given? ? yield : binding.pry
|
176
|
-
Cursor.restore_input_mode(orig_cursor_mode)
|
177
|
-
Window.set_to_full_screen if orig_fullscreen
|
178
|
-
Window.focus_window
|
109
|
+
private
|
179
110
|
|
180
|
-
|
181
|
-
|
111
|
+
def self.terminate
|
112
|
+
GLFW.DestroyWindow(Window.window)
|
113
|
+
GLFW.Terminate
|
182
114
|
end
|
183
115
|
|
184
|
-
private
|
185
|
-
|
186
116
|
def self.print_fps(delta_time)
|
187
117
|
@time_since_last_fps_print = (@time_since_last_fps_print || 0) + delta_time
|
188
118
|
@frame = (@frame || 0) + 1
|
@@ -198,24 +128,4 @@ module Engine
|
|
198
128
|
GL.Enable(GL::BLEND)
|
199
129
|
GL.BlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA)
|
200
130
|
end
|
201
|
-
|
202
|
-
def self.create_key_callbacks
|
203
|
-
GLFW::create_callback(:GLFWkeyfun) do |window, key, scancode, action, mods|
|
204
|
-
Input.key_callback(key, action)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.debug_opengl_call
|
209
|
-
errors = []
|
210
|
-
until GL.GetError == 0; end
|
211
|
-
yield
|
212
|
-
until (error = GL.GetError) == 0
|
213
|
-
errors += error.to_s(16)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def self.print_opengl_version
|
218
|
-
puts "OpenGL Version: #{GL.GetString(GL::VERSION)}"
|
219
|
-
puts "GLSL Version: #{GL.GetString(GL::SHADING_LANGUAGE_VERSION)}"
|
220
|
-
end
|
221
131
|
end
|
data/lib/engine/font.rb
CHANGED
@@ -15,7 +15,7 @@ module Engine
|
|
15
15
|
def texture
|
16
16
|
@texture ||=
|
17
17
|
begin
|
18
|
-
path = File.
|
18
|
+
path = File.join("_imported", @font_file_path.gsub(".ttf", ".png"))
|
19
19
|
Engine::Texture.for(path)
|
20
20
|
end
|
21
21
|
end
|
@@ -35,7 +35,7 @@ module Engine
|
|
35
35
|
scale_factor = 1 / (1024.0 * 2)
|
36
36
|
horizontal_offset = 0.0
|
37
37
|
vertical_offset = 0.0
|
38
|
-
font_path = File.expand_path(File.join(
|
38
|
+
font_path = File.expand_path(File.join(GAME_DIR, "_imported", @font_file_path.gsub(".ttf", ".json")))
|
39
39
|
font_metrics = JSON.parse File.read(font_path)
|
40
40
|
string.chars.each do |char|
|
41
41
|
if char == "\n"
|
data/lib/engine/game_object.rb
CHANGED
@@ -8,15 +8,17 @@ module Engine
|
|
8
8
|
@methods.add(name)
|
9
9
|
end
|
10
10
|
|
11
|
-
attr_accessor :name, :pos, :
|
11
|
+
attr_accessor :name, :pos, :scale, :components, :renderers, :ui_renderers, :created_at, :parent
|
12
12
|
|
13
13
|
def initialize(name = "Game Object", pos: Vector[0, 0, 0], rotation: 0, scale: Vector[1, 1, 1], components: [], parent: nil)
|
14
14
|
GameObject.object_spawned(self)
|
15
15
|
@pos = Vector[pos[0], pos[1], pos[2] || 0]
|
16
16
|
if rotation.is_a?(Numeric)
|
17
|
-
|
17
|
+
self.rotation = Quaternion.from_euler(Vector[0, 0, rotation])
|
18
|
+
elsif rotation.is_a?(Quaternion)
|
19
|
+
self.rotation = rotation
|
18
20
|
else
|
19
|
-
|
21
|
+
self.rotation = Quaternion.from_euler(rotation)
|
20
22
|
end
|
21
23
|
@scale = scale
|
22
24
|
@name = name
|
@@ -50,6 +52,20 @@ module Engine
|
|
50
52
|
parent.children << self if parent
|
51
53
|
end
|
52
54
|
|
55
|
+
def rotation
|
56
|
+
@rotation_quaternion
|
57
|
+
end
|
58
|
+
|
59
|
+
def rotation=(value)
|
60
|
+
raise "Rotation must be a Quaternion" unless value.is_a?(Quaternion)
|
61
|
+
|
62
|
+
@rotation_quaternion = value
|
63
|
+
end
|
64
|
+
|
65
|
+
def euler_angles
|
66
|
+
rotation.to_euler
|
67
|
+
end
|
68
|
+
|
53
69
|
def x
|
54
70
|
@pos[0]
|
55
71
|
end
|
@@ -93,16 +109,16 @@ module Engine
|
|
93
109
|
def rotate_around(axis, angle)
|
94
110
|
rotation_quaternion = Quaternion.from_angle_axis(angle, axis)
|
95
111
|
|
96
|
-
|
112
|
+
self.rotation = rotation_quaternion * rotation
|
97
113
|
end
|
98
114
|
|
99
115
|
def model_matrix
|
100
|
-
cache_key = [@pos.dup,
|
116
|
+
cache_key = [@pos.dup, rotation.dup, @scale.dup, @parent&.model_matrix&.to_a]
|
101
117
|
@model_matrix = nil if @model_matrix_cache_key != cache_key
|
102
118
|
@model_matrix_cache_key = cache_key
|
103
119
|
@model_matrix ||=
|
104
120
|
begin
|
105
|
-
rot =
|
121
|
+
rot = euler_angles * Math::PI / 180
|
106
122
|
|
107
123
|
cos_x = Math.cos(rot[0])
|
108
124
|
cos_y = Math.cos(rot[1])
|
@@ -132,17 +148,30 @@ module Engine
|
|
132
148
|
|
133
149
|
def destroy!
|
134
150
|
return unless GameObject.objects.include?(self)
|
135
|
-
|
151
|
+
children.each(&:destroy!)
|
136
152
|
components.each(&:destroy!)
|
137
153
|
ui_renderers.each(&:destroy!)
|
138
154
|
renderers.each(&:destroy!)
|
155
|
+
|
156
|
+
GameObject.destroyed_objects << self unless @destroyed
|
157
|
+
@destroyed = true
|
158
|
+
end
|
159
|
+
|
160
|
+
def _erase!
|
139
161
|
GameObject.objects.delete(self)
|
140
162
|
parent.children.delete(self) if parent
|
141
|
-
|
163
|
+
name = @name
|
142
164
|
self.class.instance_variable_get(:@methods).each do |method|
|
143
165
|
singleton_class.send(:undef_method, method)
|
144
|
-
singleton_class.send(:define_method, method) { raise "This object has been destroyed
|
166
|
+
singleton_class.send(:define_method, method) { raise "This object has been destroyed: #{name}" }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.erase_destroyed_objects
|
171
|
+
destroyed_objects.each do |object|
|
172
|
+
object._erase!
|
145
173
|
end
|
174
|
+
@destroyed_objects = []
|
146
175
|
end
|
147
176
|
|
148
177
|
def up
|
@@ -173,6 +202,9 @@ module Engine
|
|
173
202
|
GameObject.objects.each do |object|
|
174
203
|
object.components.each { |component| component.update(delta_time) }
|
175
204
|
end
|
205
|
+
|
206
|
+
Component.erase_destroyed_components
|
207
|
+
GameObject.erase_destroyed_objects
|
176
208
|
end
|
177
209
|
|
178
210
|
def self.mesh_renderers
|
@@ -194,5 +226,9 @@ module Engine
|
|
194
226
|
def self.objects
|
195
227
|
@objects ||= []
|
196
228
|
end
|
229
|
+
|
230
|
+
def self.destroyed_objects
|
231
|
+
@destroyed_objects ||= []
|
232
|
+
end
|
197
233
|
end
|
198
234
|
end
|
data/lib/engine/input.rb
CHANGED
@@ -2,6 +2,23 @@
|
|
2
2
|
|
3
3
|
module Engine
|
4
4
|
class Input
|
5
|
+
def self.init
|
6
|
+
@key_callback = GLFW::create_callback(:GLFWkeyfun) do |window, key, scancode, action, mods|
|
7
|
+
Input.key_callback(key, action)
|
8
|
+
end
|
9
|
+
GLFW.SetKeyCallback(Window.window, @key_callback)
|
10
|
+
|
11
|
+
@cursor_pos_callback = GLFW::create_callback(:GLFWcursorposfun) do |window, x, y|
|
12
|
+
Input.mouse_callback(x, y)
|
13
|
+
end
|
14
|
+
GLFW.SetCursorPosCallback(Window.window, @cursor_pos_callback)
|
15
|
+
|
16
|
+
@mouse_button_callback = GLFW::create_callback(:GLFWmousebuttonfun) do |window, button, action, mods|
|
17
|
+
Input.mouse_button_callback(button, action)
|
18
|
+
end
|
19
|
+
GLFW.SetMouseButtonCallback(Window.window, @mouse_button_callback)
|
20
|
+
end
|
21
|
+
|
5
22
|
def self.key?(key)
|
6
23
|
keys[key] == :down || keys[key] == :held
|
7
24
|
end
|
@@ -14,6 +31,17 @@ module Engine
|
|
14
31
|
keys[key] == :up
|
15
32
|
end
|
16
33
|
|
34
|
+
def self.mouse_pos
|
35
|
+
@mouse_pos
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.mouse_delta
|
39
|
+
return Vector[0, 0] if @old_mouse_pos.nil?
|
40
|
+
return Vector[0, 0] unless @mouse_pos_updated
|
41
|
+
|
42
|
+
@mouse_pos - @old_mouse_pos
|
43
|
+
end
|
44
|
+
|
17
45
|
def self._on_key_down(key)
|
18
46
|
keys[key] = :down
|
19
47
|
if key == GLFW::KEY_ESCAPE
|
@@ -21,7 +49,7 @@ module Engine
|
|
21
49
|
end
|
22
50
|
|
23
51
|
if key == GLFW::KEY_BACKSPACE
|
24
|
-
Engine.breakpoint { binding.pry }
|
52
|
+
Engine::Debugging.breakpoint { binding.pry }
|
25
53
|
# Engine.breakpoint { debugger }
|
26
54
|
end
|
27
55
|
|
@@ -42,7 +70,22 @@ module Engine
|
|
42
70
|
end
|
43
71
|
end
|
44
72
|
|
73
|
+
def self.mouse_callback(x, y)
|
74
|
+
@mouse_pos_updated = true
|
75
|
+
@old_mouse_pos = @mouse_pos
|
76
|
+
@mouse_pos = Vector[x, y]
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.mouse_button_callback(button, action)
|
80
|
+
if action == GLFW::PRESS
|
81
|
+
keys[button] = :down
|
82
|
+
elsif action == GLFW::RELEASE
|
83
|
+
keys[button] = :up
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
45
87
|
def self.update_key_states
|
88
|
+
@mouse_pos_updated = false
|
46
89
|
keys.each do |key, state|
|
47
90
|
if state == :down
|
48
91
|
keys[key] = :held
|
data/lib/engine/mesh.rb
CHANGED
@@ -21,7 +21,7 @@ module Engine
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.open_vertex(mesh_file)
|
24
|
-
vertex_cache[File.join(
|
24
|
+
vertex_cache[File.join(GAME_DIR, "_imported", mesh_file + ".vertex_data")]
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.vertex_cache
|
@@ -31,7 +31,7 @@ module Engine
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.open_index(mesh_file)
|
34
|
-
index_cache[File.join(
|
34
|
+
index_cache[File.join(GAME_DIR, "_imported", mesh_file + ".index_data")]
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.index_cache
|
data/lib/engine/quaternion.rb
CHANGED
@@ -16,6 +16,12 @@ module Engine
|
|
16
16
|
"Quaternion(w: #{@w}, x: #{@x}, y: #{@y}, z: #{@z})"
|
17
17
|
end
|
18
18
|
|
19
|
+
def ==(other)
|
20
|
+
return false unless other.is_a?(Quaternion)
|
21
|
+
|
22
|
+
@w == other.w && @x == other.x && @y == other.y && @z == other.z
|
23
|
+
end
|
24
|
+
|
19
25
|
def *(other)
|
20
26
|
Quaternion.new(
|
21
27
|
@w * other.w - @x * other.x - @y * other.y - @z * other.z,
|
data/lib/engine/texture.rb
CHANGED
@@ -12,8 +12,9 @@ module Engine
|
|
12
12
|
load_texture
|
13
13
|
end
|
14
14
|
|
15
|
-
def self.for(
|
16
|
-
|
15
|
+
def self.for(path, flip: false)
|
16
|
+
full_path = File.expand_path(File.join(GAME_DIR, path))
|
17
|
+
texture_cache[[full_path, flip]]
|
17
18
|
end
|
18
19
|
|
19
20
|
def self.texture_cache
|
data/lib/ruby_rpg.rb
CHANGED
@@ -1,3 +1,56 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'opengl'
|
4
|
+
require 'glfw'
|
5
|
+
require 'concurrent'
|
6
|
+
require 'os'
|
7
|
+
require 'native_audio'
|
8
|
+
|
9
|
+
require_relative 'engine/autoloader'
|
10
|
+
require_relative "engine/debugging"
|
11
|
+
require_relative 'engine/rendering/render_pipeline'
|
12
|
+
require_relative 'engine/rendering/instance_renderer'
|
13
|
+
require_relative 'engine/screenshoter'
|
14
|
+
require_relative 'engine/input'
|
15
|
+
require_relative "engine/quaternion"
|
16
|
+
require_relative 'engine/game_object'
|
17
|
+
require_relative 'engine/texture'
|
18
|
+
require_relative 'engine/material'
|
19
|
+
require_relative 'engine/mesh'
|
20
|
+
require_relative "engine/font"
|
21
|
+
require_relative 'engine/path'
|
22
|
+
require_relative 'engine/polygon_mesh'
|
23
|
+
require_relative 'engine/importers/obj_file'
|
24
|
+
require_relative 'engine/tangent_calculator'
|
25
|
+
require_relative 'engine/shader'
|
26
|
+
require_relative 'engine/component'
|
27
|
+
require_relative "engine/camera"
|
28
|
+
require_relative "engine/window"
|
29
|
+
require_relative "engine/video_mode"
|
30
|
+
require_relative "engine/cursor"
|
31
|
+
|
32
|
+
require_relative "engine/components/orthographic_camera"
|
33
|
+
require_relative "engine/components/perspective_camera"
|
34
|
+
require_relative "engine/components/sprite_renderer"
|
35
|
+
require_relative "engine/components/ui_sprite_renderer"
|
36
|
+
require_relative "engine/components/mesh_renderer"
|
37
|
+
require_relative "engine/components/font_renderer"
|
38
|
+
require_relative "engine/components/ui_font_renderer"
|
39
|
+
require_relative "engine/components/point_light"
|
40
|
+
require_relative "engine/components/direction_light"
|
41
|
+
require_relative "engine/components/audio_source"
|
42
|
+
|
43
|
+
require_relative "engine/physics/physics_resolver"
|
44
|
+
require_relative 'engine/physics/collision'
|
45
|
+
require_relative "engine/physics/components/sphere_collider"
|
46
|
+
require_relative "engine/physics/components/cube_collider"
|
47
|
+
require_relative "engine/physics/components/rigidbody"
|
48
|
+
|
49
|
+
if OS.windows?
|
50
|
+
GLFW.load_lib(File.expand_path(File.join(__dir__, "..", "glfw-3.4.bin.WIN64", "lib-static-ucrt", "glfw3.dll")))
|
51
|
+
elsif OS.mac?
|
52
|
+
GLFW.load_lib(File.expand_path(File.join(__dir__, "..", "glfw-3.3.9.bin.MACOS", "lib-arm64", "libglfw.3.dylib")))
|
53
|
+
end
|
54
|
+
GLFW.Init
|
55
|
+
|
3
56
|
require_relative 'engine/engine'
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_rpg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max Hatfull
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: native_audio
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: opengl-bindings2
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,7 @@ extensions: []
|
|
108
122
|
extra_rdoc_files: []
|
109
123
|
files:
|
110
124
|
- README.md
|
125
|
+
- bin/build.bash
|
111
126
|
- bin/import
|
112
127
|
- glfw-3.3.9.bin.MACOS/LICENSE.md
|
113
128
|
- glfw-3.3.9.bin.MACOS/README.md
|
@@ -537,9 +552,10 @@ files:
|
|
537
552
|
- glfw-3.4.bin.WIN64/lib-vc2022/glfw3.lib
|
538
553
|
- glfw-3.4.bin.WIN64/lib-vc2022/glfw3_mt.lib
|
539
554
|
- glfw-3.4.bin.WIN64/lib-vc2022/glfw3dll.lib
|
540
|
-
- lib/
|
555
|
+
- lib/engine/autoloader.rb
|
541
556
|
- lib/engine/camera.rb
|
542
557
|
- lib/engine/component.rb
|
558
|
+
- lib/engine/components/audio_source.rb
|
543
559
|
- lib/engine/components/direction_light.rb
|
544
560
|
- lib/engine/components/font_renderer.rb
|
545
561
|
- lib/engine/components/mesh_renderer.rb
|
@@ -550,6 +566,7 @@ files:
|
|
550
566
|
- lib/engine/components/ui_font_renderer.rb
|
551
567
|
- lib/engine/components/ui_sprite_renderer.rb
|
552
568
|
- lib/engine/cursor.rb
|
569
|
+
- lib/engine/debugging.rb
|
553
570
|
- lib/engine/engine.rb
|
554
571
|
- lib/engine/font.rb
|
555
572
|
- lib/engine/game_object.rb
|