cyberarm_engine 0.13.0 → 0.17.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +8 -0
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/LICENSE.txt +21 -21
  7. data/README.md +73 -43
  8. data/Rakefile +10 -10
  9. data/assets/textures/default.png +0 -0
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/cyberarm_engine.gemspec +39 -36
  13. data/lib/cyberarm_engine.rb +64 -47
  14. data/lib/cyberarm_engine/animator.rb +56 -54
  15. data/lib/cyberarm_engine/background.rb +179 -175
  16. data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
  17. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  18. data/lib/cyberarm_engine/cache.rb +4 -0
  19. data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
  20. data/lib/cyberarm_engine/common.rb +96 -96
  21. data/lib/cyberarm_engine/config_file.rb +46 -0
  22. data/lib/cyberarm_engine/game_object.rb +248 -257
  23. data/lib/cyberarm_engine/game_state.rb +92 -89
  24. data/lib/cyberarm_engine/model.rb +207 -0
  25. data/lib/cyberarm_engine/model/material.rb +21 -0
  26. data/lib/cyberarm_engine/model/model_object.rb +131 -0
  27. data/lib/cyberarm_engine/model/parser.rb +74 -0
  28. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
  29. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
  30. data/lib/cyberarm_engine/model_cache.rb +31 -0
  31. data/lib/cyberarm_engine/opengl.rb +28 -0
  32. data/lib/cyberarm_engine/opengl/light.rb +50 -0
  33. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
  34. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
  35. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
  36. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
  37. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
  38. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
  39. data/lib/cyberarm_engine/opengl/shader.rb +406 -0
  40. data/lib/cyberarm_engine/opengl/texture.rb +69 -0
  41. data/lib/cyberarm_engine/ray.rb +56 -56
  42. data/lib/cyberarm_engine/stats.rb +21 -0
  43. data/lib/cyberarm_engine/text.rb +160 -146
  44. data/lib/cyberarm_engine/timer.rb +23 -23
  45. data/lib/cyberarm_engine/transform.rb +296 -273
  46. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -101
  47. data/lib/cyberarm_engine/ui/dsl.rb +138 -99
  48. data/lib/cyberarm_engine/ui/element.rb +315 -276
  49. data/lib/cyberarm_engine/ui/elements/button.rb +160 -67
  50. data/lib/cyberarm_engine/ui/elements/check_box.rb +51 -59
  51. data/lib/cyberarm_engine/ui/elements/container.rb +256 -176
  52. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -0
  53. data/lib/cyberarm_engine/ui/elements/edit_line.rb +262 -172
  54. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -17
  55. data/lib/cyberarm_engine/ui/elements/image.rb +72 -52
  56. data/lib/cyberarm_engine/ui/elements/label.rb +156 -50
  57. data/lib/cyberarm_engine/ui/elements/list_box.rb +82 -0
  58. data/lib/cyberarm_engine/ui/elements/progress.rb +51 -50
  59. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -0
  60. data/lib/cyberarm_engine/ui/elements/slider.rb +104 -0
  61. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -13
  62. data/lib/cyberarm_engine/ui/elements/text_block.rb +156 -0
  63. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +65 -56
  64. data/lib/cyberarm_engine/ui/event.rb +47 -47
  65. data/lib/cyberarm_engine/ui/gui_state.rb +226 -135
  66. data/lib/cyberarm_engine/ui/style.rb +38 -37
  67. data/lib/cyberarm_engine/ui/theme.rb +182 -120
  68. data/lib/cyberarm_engine/vector.rb +293 -203
  69. data/lib/cyberarm_engine/version.rb +4 -4
  70. data/lib/cyberarm_engine/{engine.rb → window.rb} +114 -101
  71. metadata +88 -18
  72. data/lib/cyberarm_engine/gosu_ext/circle.rb +0 -9
  73. data/lib/cyberarm_engine/shader.rb +0 -262
@@ -0,0 +1,69 @@
1
+ module CyberarmEngine
2
+ class Texture
3
+ DEFAULT_TEXTURE = "#{CYBERARM_ENGINE_ROOT_PATH}/assets/textures/default.png".freeze
4
+
5
+ CACHE = {}
6
+
7
+ def self.release_textures
8
+ CACHE.values.each do |id|
9
+ glDeleteTextures(id)
10
+ end
11
+ end
12
+
13
+ def self.from_cache(path, retro)
14
+ CACHE.dig("#{path}?retro=#{retro}")
15
+ end
16
+
17
+ attr_reader :id
18
+
19
+ def initialize(path: nil, image: nil, retro: false)
20
+ raise "keyword :path or :image must be provided!" if path.nil? && image.nil?
21
+
22
+ @retro = retro
23
+ @path = path
24
+
25
+ if @path
26
+ unless File.exist?(@path)
27
+ warn "Missing texture at: #{@path}"
28
+ @retro = true # override retro setting
29
+ @path = DEFAULT_TEXTURE
30
+ end
31
+
32
+ if texture = Texture.from_cache(@path, @retro)
33
+ @id = texture.id
34
+ return
35
+ end
36
+
37
+ image = load_image(@path)
38
+ @id = create_from_image(image)
39
+ else
40
+ @id = create_from_image(image)
41
+ end
42
+ end
43
+
44
+ def load_image(path)
45
+ CACHE["#{path}?retro=#{@retro}"] = self
46
+ Gosu::Image.new(path, retro: @retro)
47
+ end
48
+
49
+ def create_from_image(image)
50
+ array_of_pixels = image.to_blob
51
+
52
+ tex_names_buf = " " * 4
53
+ glGenTextures(1, tex_names_buf)
54
+ texture_id = tex_names_buf.unpack1("L2")
55
+
56
+ glBindTexture(GL_TEXTURE_2D, texture_id)
57
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, array_of_pixels)
58
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
59
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
60
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) if @retro
61
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) unless @retro
62
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
63
+ glGenerateMipmap(GL_TEXTURE_2D)
64
+ gl_error?
65
+
66
+ texture_id
67
+ end
68
+ end
69
+ end
@@ -1,56 +1,56 @@
1
- module CyberarmEngine
2
- class Ray
3
- def initialize(origin, direction, range = Float::INFINITY)
4
- raise "Origin must be a Vector!" unless origin.is_a?(Vector)
5
- raise "Direction must be a Vector!" unless direction.is_a?(Vector)
6
-
7
- @origin = origin
8
- @direction = direction
9
- @range = range
10
-
11
- @inverse_direction = @direction.inverse
12
- end
13
-
14
- def intersect?(intersectable)
15
- if intersectable.is_a?(BoundingBox)
16
- intersect_bounding_box?(intersectable)
17
- else
18
- raise NotImplementedError, "Ray intersection test for #{intersectable.class} not implemented."
19
- end
20
- end
21
-
22
- # Based on: https://tavianator.com/fast-branchless-raybounding-box-intersections/
23
- def intersect_bounding_box?(box)
24
- tmin = -@range
25
- tmax = @range
26
-
27
- tx1 = (box.min.x - @origin.x) * @inverse_direction.x
28
- tx2 = (box.max.x - @origin.x) * @inverse_direction.x
29
-
30
- tmin = max(tmin, min(tx1, tx2))
31
- tmax = min(tmax, max(tx1, tx2))
32
-
33
- ty1 = (box.min.y - @origin.y) * @inverse_direction.y
34
- ty2 = (box.max.y - @origin.y) * @inverse_direction.y
35
-
36
- tmin = max(tmin, min(ty1, ty2))
37
- tmax = min(tmax, max(ty1, ty2))
38
-
39
- tz1 = (box.min.z - @origin.z) * @inverse_direction.z
40
- tz2 = (box.max.z - @origin.z) * @inverse_direction.z
41
-
42
- tmin = max(tmin, min(tz1, tz2))
43
- tmax = min(tmax, max(tz1, tz2))
44
-
45
- return tmax >= max(tmin, 0.0);
46
- end
47
-
48
- def min(x, y)
49
- ((x) < (y) ? (x) : (y))
50
- end
51
-
52
- def max(x, y)
53
- ((x) > (y) ? (x) : (y))
54
- end
55
- end
56
- end
1
+ module CyberarmEngine
2
+ class Ray
3
+ def initialize(origin, direction, range = Float::INFINITY)
4
+ raise "Origin must be a Vector!" unless origin.is_a?(Vector)
5
+ raise "Direction must be a Vector!" unless direction.is_a?(Vector)
6
+
7
+ @origin = origin
8
+ @direction = direction
9
+ @range = range
10
+
11
+ @inverse_direction = @direction.inverse
12
+ end
13
+
14
+ def intersect?(intersectable)
15
+ if intersectable.is_a?(BoundingBox)
16
+ intersect_bounding_box?(intersectable)
17
+ else
18
+ raise NotImplementedError, "Ray intersection test for #{intersectable.class} not implemented."
19
+ end
20
+ end
21
+
22
+ # Based on: https://tavianator.com/fast-branchless-raybounding-box-intersections/
23
+ def intersect_bounding_box?(box)
24
+ tmin = -@range
25
+ tmax = @range
26
+
27
+ tx1 = (box.min.x - @origin.x) * @inverse_direction.x
28
+ tx2 = (box.max.x - @origin.x) * @inverse_direction.x
29
+
30
+ tmin = max(tmin, min(tx1, tx2))
31
+ tmax = min(tmax, max(tx1, tx2))
32
+
33
+ ty1 = (box.min.y - @origin.y) * @inverse_direction.y
34
+ ty2 = (box.max.y - @origin.y) * @inverse_direction.y
35
+
36
+ tmin = max(tmin, min(ty1, ty2))
37
+ tmax = min(tmax, max(ty1, ty2))
38
+
39
+ tz1 = (box.min.z - @origin.z) * @inverse_direction.z
40
+ tz2 = (box.max.z - @origin.z) * @inverse_direction.z
41
+
42
+ tmin = max(tmin, min(tz1, tz2))
43
+ tmax = min(tmax, max(tz1, tz2))
44
+
45
+ tmax >= max(tmin, 0.0)
46
+ end
47
+
48
+ def min(x, y)
49
+ ((x) < (y) ? x : y)
50
+ end
51
+
52
+ def max(x, y)
53
+ ((x) > (y) ? x : y)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,21 @@
1
+ module CyberarmEngine
2
+ class Stats
3
+ @@hash = {
4
+ gui_recalculations_last_frame: 0
5
+ }
6
+
7
+ def self.get(key)
8
+ @@hash.dig(key)
9
+ end
10
+
11
+ def self.increment(key, n)
12
+ @@hash[key] += n
13
+ end
14
+
15
+ def self.clear
16
+ @@hash.each do |key, _value|
17
+ @@hash[key] = 0
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,146 +1,160 @@
1
- module CyberarmEngine
2
- class Text
3
- CACHE = {}
4
-
5
- attr_accessor :x, :y, :z, :size, :options
6
- attr_reader :text, :textobject, :factor_x, :factor_y, :color, :shadow, :shadow_size, :shadow_alpha, :shadow_color
7
-
8
- def initialize(text, options={})
9
- @text = text.to_s || ""
10
- @options = options
11
- @size = options[:size] || 18
12
- @font = options[:font] || "sans-serif"#Gosu.default_font_name
13
- @x = options[:x] || 0
14
- @y = options[:y] || 0
15
- @z = options[:z] || 1025
16
- @factor_x = options[:factor_x] || 1
17
- @factor_y = options[:factor_y] || 1
18
- @color = options[:color] || Gosu::Color::WHITE
19
- @alignment= options[:alignment] || nil
20
- @shadow = true if options[:shadow] == true
21
- @shadow = false if options[:shadow] == false
22
- @shadow = true if options[:shadow] == nil
23
- @shadow_size = options[:shadow_size] ? options[:shadow_size] : 1
24
- @shadow_alpha= options[:shadow_alpha] ? options[:shadow_alpha] : 30
25
- @shadow_alpha= options[:shadow_alpha] ? options[:shadow_alpha] : 30
26
- @shadow_color= options[:shadow_color]
27
- @textobject = check_cache(@size, @font)
28
-
29
- if @alignment
30
- case @alignment
31
- when :left
32
- @x = 0+BUTTON_PADDING
33
- when :center
34
- @x = ($window.width/2)-(@textobject.text_width(@text)/2)
35
- when :right
36
- @x = $window.width-BUTTON_PADDING-@textobject.text_width(@text)
37
- end
38
- end
39
-
40
- return self
41
- end
42
-
43
- def check_cache(size, font_name)
44
- available = false
45
- font = nil
46
-
47
- if CACHE[size]
48
- if CACHE[size][font_name]
49
- font = CACHE[size][font_name]
50
- available = true
51
- else
52
- available = false
53
- end
54
- else
55
- available = false
56
- end
57
-
58
- unless available
59
- font = Gosu::Font.new(@size, name: @font)
60
- CACHE[@size] = {} unless CACHE[@size].is_a?(Hash)
61
- CACHE[@size][@font] = font
62
- end
63
-
64
- return font
65
- end
66
-
67
- def text=(string)
68
- @rendered_shadow = nil
69
- @text = string
70
- end
71
-
72
- def factor_x=(n)
73
- @rendered_shadow = nil
74
- @factor_x = n
75
- end
76
- def factor_y=(n)
77
- @rendered_shadow = nil
78
- @factor_y = n
79
- end
80
- def color=(color)
81
- @rendered_shadow = nil
82
- @color = color
83
- end
84
- def shadow=(boolean)
85
- @rendered_shadow = nil
86
- @shadow = boolean
87
- end
88
- def shadow_size=(n)
89
- @rendered_shadow = nil
90
- @shadow_size = n
91
- end
92
- def shadow_alpha=(n)
93
- @rendered_shadow = nil
94
- @shadow_alpha = n
95
- end
96
- def shadow_color=(n)
97
- @rendered_shadow = nil
98
- @shadow_color = n
99
- end
100
-
101
- def width
102
- textobject.text_width(@text)
103
- end
104
-
105
- def height
106
- @text.lines.count > 0 ? (@text.lines.count) * textobject.height : @textobject.height
107
- end
108
-
109
- def draw
110
- if @shadow && !ARGV.join.include?("--no-shadow")
111
- shadow_alpha = @color.alpha <= 30 ? @color.alpha : @shadow_alpha
112
- shadow_color = @shadow_color ? @shadow_color : Gosu::Color.rgba(@color.red, @color.green, @color.blue, shadow_alpha)
113
-
114
- _x = @shadow_size
115
- _y = @shadow_size
116
-
117
- @rendered_shadow ||= Gosu.render((self.width+(shadow_size*2)).ceil, (self.height+(@shadow_size*2)).ceil) do
118
- @textobject.draw_markup(@text, _x-@shadow_size, _y, @z)
119
- @textobject.draw_markup(@text, _x-@shadow_size, _y-@shadow_size, @z)
120
-
121
- @textobject.draw_markup(@text, _x, _y-@shadow_size, @z, @factor_x)
122
- @textobject.draw_markup(@text, _x+@shadow_size, _y-@shadow_size, @z)
123
-
124
- @textobject.draw_markup(@text, _x, _y+@shadow_size, @z)
125
- @textobject.draw_markup(@text, _x-@shadow_size, _y+@shadow_size, @z)
126
-
127
- @textobject.draw_markup(@text, _x+@shadow_size, _y, @z)
128
- @textobject.draw_markup(@text, _x+@shadow_size, _y+@shadow_size, @z)
129
- end
130
- @rendered_shadow.draw(@x-@shadow_size, @y-@shadow_size, @z, @factor_x, @factor_y, shadow_color)
131
- end
132
-
133
- @textobject.draw_markup(@text, @x, @y, @z, @factor_x, @factor_y, @color)
134
- end
135
-
136
- def alpha=(n)
137
- @color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, n)
138
- end
139
-
140
- def alpha
141
- @color.alpha
142
- end
143
-
144
- def update; end
145
- end
146
- end
1
+ module CyberarmEngine
2
+ class Text
3
+ CACHE = {}
4
+
5
+ attr_accessor :x, :y, :z, :size, :options
6
+ attr_reader :text, :textobject, :factor_x, :factor_y, :color, :shadow, :shadow_size, :shadow_alpha, :shadow_color
7
+
8
+ def initialize(text, options = {})
9
+ @text = text.to_s || ""
10
+ @options = options
11
+ @size = options[:size] || 18
12
+ @font = options[:font] || Gosu.default_font_name
13
+ @x = options[:x] || 0
14
+ @y = options[:y] || 0
15
+ @z = options[:z] || 1025
16
+ @factor_x = options[:factor_x] || 1
17
+ @factor_y = options[:factor_y] || 1
18
+ @color = options[:color] || Gosu::Color::WHITE
19
+ @mode = options[:mode] || :default
20
+ @alignment = options[:alignment] || nil
21
+ @shadow = true if options[:shadow] == true
22
+ @shadow = false if options[:shadow] == false
23
+ @shadow = true if options[:shadow].nil?
24
+ @shadow_size = options[:shadow_size] || 1
25
+ @shadow_alpha = options[:shadow_alpha] || 30
26
+ @shadow_alpha = options[:shadow_alpha] || 30
27
+ @shadow_color = options[:shadow_color]
28
+ @textobject = check_cache(@size, @font)
29
+
30
+ if @alignment
31
+ case @alignment
32
+ when :left
33
+ @x = 0 + BUTTON_PADDING
34
+ when :center
35
+ @x = ($window.width / 2) - (@textobject.text_width(@text) / 2)
36
+ when :right
37
+ @x = $window.width - BUTTON_PADDING - @textobject.text_width(@text)
38
+ end
39
+ end
40
+
41
+ self
42
+ end
43
+
44
+ def check_cache(size, font_name)
45
+ available = false
46
+ font = nil
47
+
48
+ if CACHE[size]
49
+ if CACHE[size][font_name]
50
+ font = CACHE[size][font_name]
51
+ available = true
52
+ else
53
+ available = false
54
+ end
55
+ else
56
+ available = false
57
+ end
58
+
59
+ unless available
60
+ font = Gosu::Font.new(@size, name: @font)
61
+ CACHE[@size] = {} unless CACHE[@size].is_a?(Hash)
62
+ CACHE[@size][@font] = font
63
+ end
64
+
65
+ font
66
+ end
67
+
68
+ def text=(string)
69
+ @rendered_shadow = nil
70
+ @text = string
71
+ end
72
+
73
+ def factor_x=(n)
74
+ @rendered_shadow = nil
75
+ @factor_x = n
76
+ end
77
+
78
+ def factor_y=(n)
79
+ @rendered_shadow = nil
80
+ @factor_y = n
81
+ end
82
+
83
+ def color=(color)
84
+ @rendered_shadow = nil
85
+ @color = color
86
+ end
87
+
88
+ def shadow=(boolean)
89
+ @rendered_shadow = nil
90
+ @shadow = boolean
91
+ end
92
+
93
+ def shadow_size=(n)
94
+ @rendered_shadow = nil
95
+ @shadow_size = n
96
+ end
97
+
98
+ def shadow_alpha=(n)
99
+ @rendered_shadow = nil
100
+ @shadow_alpha = n
101
+ end
102
+
103
+ def shadow_color=(n)
104
+ @rendered_shadow = nil
105
+ @shadow_color = n
106
+ end
107
+
108
+ def width(text = @text)
109
+ textobject.text_width(text)
110
+ end
111
+
112
+ def markup_width(text = @text)
113
+ textobject.markup_width(text)
114
+ end
115
+
116
+ def height(text = @text)
117
+ text.lines.count > 0 ? text.lines.count * textobject.height : @textobject.height
118
+ end
119
+
120
+ def draw(method = :draw_markup)
121
+ if @shadow && !ARGV.join.include?("--no-shadow")
122
+ shadow_alpha = @color.alpha <= 30 ? @color.alpha : @shadow_alpha
123
+ shadow_color = @shadow_color || Gosu::Color.rgba(@color.red, @color.green, @color.blue,
124
+ shadow_alpha)
125
+ white = Gosu::Color::WHITE
126
+
127
+ _x = @shadow_size
128
+ _y = @shadow_size
129
+
130
+ @rendered_shadow ||= Gosu.render((width + (shadow_size * 2)).ceil, (height + (@shadow_size * 2)).ceil) do
131
+ @textobject.send(method, @text, _x - @shadow_size, _y, @z, @factor_x, @factor_y, white, :add)
132
+ @textobject.send(method, @text, _x - @shadow_size, _y - @shadow_size, @z, @factor_x, @factor_y, white, :add)
133
+
134
+ @textobject.send(method, @text, _x, _y - @shadow_size, @z, @factor_x, @factor_y, white, :add)
135
+ @textobject.send(method, @text, _x + @shadow_size, _y - @shadow_size, @z, @factor_x, @factor_y, white, :add)
136
+
137
+ @textobject.send(method, @text, _x, _y + @shadow_size, @z, @factor_x, @factor_y, white, :add)
138
+ @textobject.send(method, @text, _x - @shadow_size, _y + @shadow_size, @z, @factor_x, @factor_y, white, :add)
139
+
140
+ @textobject.send(method, @text, _x + @shadow_size, _y, @z, @factor_x, @factor_y, white, :add)
141
+ @textobject.send(method, @text, _x + @shadow_size, _y + @shadow_size, @z, @factor_x, @factor_y, white, :add)
142
+ end
143
+ @rendered_shadow.draw(@x - @shadow_size, @y - @shadow_size, @z, @factor_x, @factor_y, shadow_color)
144
+ end
145
+
146
+ @textobject.send(method, @text, @x, @y, @z, @factor_x, @factor_y, @color, @mode)
147
+ end
148
+
149
+ def alpha=(n)
150
+ @color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, n)
151
+ end
152
+
153
+ def alpha
154
+ @color.alpha
155
+ end
156
+
157
+ def update
158
+ end
159
+ end
160
+ end