ruby_rpg 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bb1056bb375c7c3ebbbdf7b2b23f1b5ad1fd6ddec9c0f2e63713aef56f345f7
4
- data.tar.gz: bead66754d17fafe491808aa0cef827cbc789ea718e61e114b53599b2c619b43
3
+ metadata.gz: b56f66eb45701f903472f4d948d42e1a67a9bf051c59e0515ee8df1195503d7e
4
+ data.tar.gz: 35e50569d84181202098fd7425025ef73bdc54d0d7eae16bef0ad0acbe1fb6fb
5
5
  SHA512:
6
- metadata.gz: c3560e6b6aad6e80b3ace11b49c86a671eea0634b05b57383358921520502c476f0147f4aa39a21852149a8c4c866888cdd23aeee28fcb90517d5da975f385a5
7
- data.tar.gz: 55c62ec5c13331a3bef15c3badac233bb23d66fca4c3d3cd273161e66c256ba6032ccc47c552c1c474ba9f3ff21e12fb0211de215aaa10e200283829f19a85fb
6
+ metadata.gz: '08ec8719dae3c6788e4aa692059706ed9635b540974164339c4a5887dc0a0a420b48d8b7abc4022f87b899b8e2c02674d060107ec8c3dad06dcd6431add8f433'
7
+ data.tar.gz: a65cadf65c339c7b656c825dfa1ea6365e6fb2c94f090396b3e11c4e515d78b45819447bd186ebfb79424ed5fc25689d66cb4ed4a59b76c7e0ad7b5d943a187d
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
- TODO: Write installation instructions here
8
+ You can find full instructions on th [wiki](https://github.com/rubyrpg/ruby_rpg/wiki/Installation).
9
9
 
10
10
  ## Usage
11
- TODO: Write usage instructions here
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
@@ -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 glfw-3.4.bin.WIN64/**/* src/**/*.rb \
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
@@ -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
- destroy
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
@@ -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
- require 'opengl'
2
- require 'glfw'
3
- require 'concurrent'
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(base_dir:, &first_frame_block)
52
- load(base_dir)
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,12 +16,6 @@ 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
@@ -144,13 +93,10 @@ module Engine
144
93
  @fps
145
94
  end
146
95
 
147
- def self.terminate
148
- GLFW.DestroyWindow(Window.window)
149
- GLFW.Terminate
150
- end
151
-
152
96
  def self.close
153
97
  GameObject.destroy_all
98
+ Component.erase_destroyed_components
99
+ GameObject.erase_destroyed_objects
154
100
  GLFW.SetWindowShouldClose(Window.window, 1)
155
101
  end
156
102
 
@@ -158,31 +104,17 @@ module Engine
158
104
  @game_stopped = true
159
105
  @swap_buffers_promise.wait! if @swap_buffers_promise && !@swap_buffers_promise.complete?
160
106
  GameObject.destroy_all
107
+ Component.erase_destroyed_components
108
+ GameObject.erase_destroyed_objects
161
109
  end
162
110
 
163
- # Hit a breakpoint within the context of where the breakpoint is defined, assuming a block is passed
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
111
+ private
179
112
 
180
- # Reset the time, otherwise delta_time will be off for the next frame, and teleporting occurs
181
- @time = Time.now
113
+ def self.terminate
114
+ GLFW.DestroyWindow(Window.window)
115
+ GLFW.Terminate
182
116
  end
183
117
 
184
- private
185
-
186
118
  def self.print_fps(delta_time)
187
119
  @time_since_last_fps_print = (@time_since_last_fps_print || 0) + delta_time
188
120
  @frame = (@frame || 0) + 1
@@ -204,18 +136,4 @@ module Engine
204
136
  Input.key_callback(key, action)
205
137
  end
206
138
  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
139
  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.expand_path(File.join(ROOT, "_imported", @font_file_path.gsub(".ttf", ".png")))
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(ROOT, "_imported", @font_file_path.gsub(".ttf", ".json")))
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"
@@ -132,17 +132,30 @@ module Engine
132
132
 
133
133
  def destroy!
134
134
  return unless GameObject.objects.include?(self)
135
- @destroyed = true
135
+ children.each(&:destroy!)
136
136
  components.each(&:destroy!)
137
137
  ui_renderers.each(&:destroy!)
138
138
  renderers.each(&:destroy!)
139
+
140
+ GameObject.destroyed_objects << self unless @destroyed
141
+ @destroyed = true
142
+ end
143
+
144
+ def _erase!
139
145
  GameObject.objects.delete(self)
140
146
  parent.children.delete(self) if parent
141
- children.each(&:destroy!)
147
+ name = @name
142
148
  self.class.instance_variable_get(:@methods).each do |method|
143
149
  singleton_class.send(:undef_method, method)
144
- singleton_class.send(:define_method, method) { raise "This object has been destroyed. Object ID: #{self.object_id}" }
150
+ singleton_class.send(:define_method, method) { raise "This object has been destroyed: #{name}" }
151
+ end
152
+ end
153
+
154
+ def self.erase_destroyed_objects
155
+ destroyed_objects.each do |object|
156
+ object._erase!
145
157
  end
158
+ @destroyed_objects = []
146
159
  end
147
160
 
148
161
  def up
@@ -173,6 +186,9 @@ module Engine
173
186
  GameObject.objects.each do |object|
174
187
  object.components.each { |component| component.update(delta_time) }
175
188
  end
189
+
190
+ Component.erase_destroyed_components
191
+ GameObject.erase_destroyed_objects
176
192
  end
177
193
 
178
194
  def self.mesh_renderers
@@ -194,5 +210,9 @@ module Engine
194
210
  def self.objects
195
211
  @objects ||= []
196
212
  end
213
+
214
+ def self.destroyed_objects
215
+ @destroyed_objects ||= []
216
+ end
197
217
  end
198
218
  end
data/lib/engine/input.rb CHANGED
@@ -21,7 +21,7 @@ module Engine
21
21
  end
22
22
 
23
23
  if key == GLFW::KEY_BACKSPACE
24
- Engine.breakpoint { binding.pry }
24
+ Engine::Debugging.breakpoint { binding.pry }
25
25
  # Engine.breakpoint { debugger }
26
26
  end
27
27
 
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(ROOT, "_imported", mesh_file + ".vertex_data")]
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(ROOT, "_imported", mesh_file + ".index_data")]
34
+ index_cache[File.join(GAME_DIR, "_imported", mesh_file + ".index_data")]
35
35
  end
36
36
 
37
37
  def self.index_cache
@@ -12,8 +12,9 @@ module Engine
12
12
  load_texture
13
13
  end
14
14
 
15
- def self.for(file_path, flip: false)
16
- texture_cache[[file_path, flip]]
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.2
4
+ version: 0.0.3
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-10-27 00:00:00.000000000 Z
11
+ date: 2024-11-04 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/build.bash
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