cyberarm_engine 0.13.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
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