cyberarm_engine 0.12.1 → 0.13.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/.gitignore +8 -8
- data/.travis.yml +5 -5
- data/Gemfile +6 -6
- data/LICENSE.txt +21 -21
- data/README.md +43 -43
- data/Rakefile +10 -10
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/cyberarm_engine.gemspec +36 -36
- data/lib/cyberarm_engine.rb +47 -46
- data/lib/cyberarm_engine/animator.rb +54 -0
- data/lib/cyberarm_engine/background.rb +175 -175
- data/lib/cyberarm_engine/bounding_box.rb +149 -149
- data/lib/cyberarm_engine/common.rb +96 -96
- data/lib/cyberarm_engine/engine.rb +101 -101
- data/lib/cyberarm_engine/game_object.rb +256 -256
- data/lib/cyberarm_engine/game_state.rb +88 -88
- data/lib/cyberarm_engine/gosu_ext/circle.rb +8 -8
- data/lib/cyberarm_engine/ray.rb +55 -55
- data/lib/cyberarm_engine/shader.rb +262 -205
- data/lib/cyberarm_engine/text.rb +146 -146
- data/lib/cyberarm_engine/timer.rb +22 -22
- data/lib/cyberarm_engine/transform.rb +272 -83
- data/lib/cyberarm_engine/ui/border_canvas.rb +100 -100
- data/lib/cyberarm_engine/ui/dsl.rb +98 -101
- data/lib/cyberarm_engine/ui/element.rb +275 -259
- data/lib/cyberarm_engine/ui/elements/button.rb +66 -66
- data/lib/cyberarm_engine/ui/elements/check_box.rb +58 -58
- data/lib/cyberarm_engine/ui/elements/container.rb +176 -162
- data/lib/cyberarm_engine/ui/elements/edit_line.rb +171 -102
- data/lib/cyberarm_engine/ui/elements/flow.rb +16 -16
- data/lib/cyberarm_engine/ui/elements/image.rb +51 -51
- data/lib/cyberarm_engine/ui/elements/label.rb +49 -49
- data/lib/cyberarm_engine/ui/elements/progress.rb +49 -49
- data/lib/cyberarm_engine/ui/elements/stack.rb +12 -12
- data/lib/cyberarm_engine/ui/elements/toggle_button.rb +55 -55
- data/lib/cyberarm_engine/ui/event.rb +46 -45
- data/lib/cyberarm_engine/ui/gui_state.rb +134 -134
- data/lib/cyberarm_engine/ui/style.rb +36 -36
- data/lib/cyberarm_engine/ui/theme.rb +120 -119
- data/lib/cyberarm_engine/vector.rb +202 -198
- data/lib/cyberarm_engine/version.rb +4 -4
- metadata +6 -5
@@ -1,175 +1,175 @@
|
|
1
|
-
module CyberarmEngine
|
2
|
-
class Background
|
3
|
-
attr_accessor :x, :y, :z, :width, :height, :angle, :debug
|
4
|
-
attr_reader :background
|
5
|
-
def initialize(x: 0, y: 0, z: 0, width: 0, height: 0, background: Gosu::Color::BLACK, angle: 0, debug: false)
|
6
|
-
@x,@y,@z = x,y,z
|
7
|
-
@width,@height = width,height
|
8
|
-
@debug = debug
|
9
|
-
|
10
|
-
@paint = Paint.new(background)
|
11
|
-
@angle = angle
|
12
|
-
|
13
|
-
@top_left = Vector.new(@x, @y)
|
14
|
-
@top_right = Vector.new(@x + @width, @y)
|
15
|
-
@bottom_left = Vector.new(@x, @y + @height)
|
16
|
-
@bottom_right = Vector.new(@x + @width, @y + @height)
|
17
|
-
end
|
18
|
-
|
19
|
-
def draw
|
20
|
-
Gosu.clip_to(@x, @y, @width, @height) do
|
21
|
-
Gosu.draw_quad(
|
22
|
-
@top_left.x, @top_left.y, @paint.top_left,
|
23
|
-
@top_right.x, @top_right.y, @paint.top_right,
|
24
|
-
@bottom_right.x, @bottom_right.y, @paint.bottom_right,
|
25
|
-
@bottom_left.x, @bottom_left.y, @paint.bottom_left,
|
26
|
-
@z
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
debug_outline if @debug
|
31
|
-
end
|
32
|
-
|
33
|
-
def update
|
34
|
-
origin_x = (@x + (@width/2))
|
35
|
-
origin_y = (@y + (@height/2))
|
36
|
-
|
37
|
-
points = [
|
38
|
-
@top_left = Vector.new(@x, @y),
|
39
|
-
@top_right = Vector.new(@x + @width, @y),
|
40
|
-
@bottom_left = Vector.new(@x, @y + @height),
|
41
|
-
@bottom_right = Vector.new(@x + @width, @y + @height)
|
42
|
-
]
|
43
|
-
|
44
|
-
[@top_left, @top_right, @bottom_left, @bottom_right].each do |vector|
|
45
|
-
temp_x = vector.x - origin_x
|
46
|
-
temp_y = vector.y - origin_y
|
47
|
-
|
48
|
-
# 90 is up here, while gosu uses 0 for up.
|
49
|
-
radians = (@angle + 90).gosu_to_radians
|
50
|
-
vector.x = (@x + (@width/2)) + ((temp_x * Math.cos(radians)) - (temp_y * Math.sin(radians)))
|
51
|
-
vector.y = (@y + (@height/2)) + ((temp_x * Math.sin(radians)) + (temp_y * Math.cos(radians)))
|
52
|
-
end
|
53
|
-
|
54
|
-
# [
|
55
|
-
# [:top, @top_left, @top_right],
|
56
|
-
# [:right, @top_right, @bottom_right],
|
57
|
-
# [:bottom, @bottom_right, @bottom_left],
|
58
|
-
# [:left, @bottom_left, @top_left]
|
59
|
-
# ].each do |edge|
|
60
|
-
# points.each do |point|
|
61
|
-
# puts "#{edge.first} -> #{shortest_distance(point, edge[1], edge[2])}"
|
62
|
-
# end
|
63
|
-
# end
|
64
|
-
end
|
65
|
-
|
66
|
-
def shortest_distance(point, la, lb)
|
67
|
-
a = la.x - lb.x
|
68
|
-
b = la.y - lb.y
|
69
|
-
c = Gosu.distance(la.x, la.y, lb.x, lb.y)
|
70
|
-
p a,b,c
|
71
|
-
d = (a * point.x + b * point.y + c).abs / (Math.sqrt(a * a + b * b))
|
72
|
-
puts "Distance: #{d}"
|
73
|
-
exit!
|
74
|
-
return d
|
75
|
-
end
|
76
|
-
|
77
|
-
def debug_outline
|
78
|
-
# Top
|
79
|
-
Gosu.draw_line(
|
80
|
-
@x, @y, Gosu::Color::RED,
|
81
|
-
@x + @width, @y, Gosu::Color::RED,
|
82
|
-
@z
|
83
|
-
)
|
84
|
-
|
85
|
-
# Right
|
86
|
-
Gosu.draw_line(
|
87
|
-
@x + @width, @y, Gosu::Color::RED,
|
88
|
-
@x + @width, @y + @height, Gosu::Color::RED,
|
89
|
-
@z
|
90
|
-
)
|
91
|
-
|
92
|
-
# Bottom
|
93
|
-
Gosu.draw_line(
|
94
|
-
@x + @width, @y + @height, Gosu::Color::RED,
|
95
|
-
@x, @y + @height, Gosu::Color::RED,
|
96
|
-
@z
|
97
|
-
)
|
98
|
-
|
99
|
-
# Left
|
100
|
-
Gosu.draw_line(
|
101
|
-
@x, @y + @height, Gosu::Color::RED,
|
102
|
-
@x, @y, Gosu::Color::RED,
|
103
|
-
@z
|
104
|
-
)
|
105
|
-
end
|
106
|
-
|
107
|
-
def background=(_background)
|
108
|
-
@paint.set(_background)
|
109
|
-
update
|
110
|
-
end
|
111
|
-
|
112
|
-
def angle=(n)
|
113
|
-
@angle = n
|
114
|
-
update
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
class Paint
|
119
|
-
attr_accessor :top_left, :top_right, :bottom_left, :bottom_right
|
120
|
-
def initialize(background)
|
121
|
-
set(background)
|
122
|
-
end
|
123
|
-
|
124
|
-
def set(background)
|
125
|
-
@background = background
|
126
|
-
|
127
|
-
|
128
|
-
if background.is_a?(Numeric)
|
129
|
-
@top_left = background
|
130
|
-
@top_right = background
|
131
|
-
@bottom_left = background
|
132
|
-
@bottom_right = background
|
133
|
-
elsif background.is_a?(Gosu::Color)
|
134
|
-
@top_left = background
|
135
|
-
@top_right = background
|
136
|
-
@bottom_left = background
|
137
|
-
@bottom_right = background
|
138
|
-
elsif background.is_a?(Array)
|
139
|
-
if background.size == 1
|
140
|
-
set(background.first)
|
141
|
-
elsif background.size == 2
|
142
|
-
@top_left = background.first
|
143
|
-
@top_right = background.last
|
144
|
-
@bottom_left = background.first
|
145
|
-
@bottom_right = background.last
|
146
|
-
elsif background.size == 4
|
147
|
-
@top_left = background[0]
|
148
|
-
@top_right = background[1]
|
149
|
-
@bottom_left = background[2]
|
150
|
-
@bottom_right = background[3]
|
151
|
-
else
|
152
|
-
raise ArgumentError, "background array was empty or had wrong number of elements (expected 2 or 4 elements)"
|
153
|
-
end
|
154
|
-
elsif background.is_a?(Hash)
|
155
|
-
@top_left = background[:top_left]
|
156
|
-
@top_right = background[:top_right]
|
157
|
-
@bottom_left = background[:bottom_left]
|
158
|
-
@bottom_right = background[:bottom_right]
|
159
|
-
elsif background.is_a?(Range)
|
160
|
-
set([background.begin, background.begin, background.end, background.end])
|
161
|
-
else
|
162
|
-
raise ArgumentError, "background '#{background}' of type '#{background.class}' was not able to be processed"
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
# Add <=> method to support Range based gradients
|
169
|
-
module Gosu
|
170
|
-
class Color
|
171
|
-
def <=>(other)
|
172
|
-
self
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
1
|
+
module CyberarmEngine
|
2
|
+
class Background
|
3
|
+
attr_accessor :x, :y, :z, :width, :height, :angle, :debug
|
4
|
+
attr_reader :background
|
5
|
+
def initialize(x: 0, y: 0, z: 0, width: 0, height: 0, background: Gosu::Color::BLACK, angle: 0, debug: false)
|
6
|
+
@x,@y,@z = x,y,z
|
7
|
+
@width,@height = width,height
|
8
|
+
@debug = debug
|
9
|
+
|
10
|
+
@paint = Paint.new(background)
|
11
|
+
@angle = angle
|
12
|
+
|
13
|
+
@top_left = Vector.new(@x, @y)
|
14
|
+
@top_right = Vector.new(@x + @width, @y)
|
15
|
+
@bottom_left = Vector.new(@x, @y + @height)
|
16
|
+
@bottom_right = Vector.new(@x + @width, @y + @height)
|
17
|
+
end
|
18
|
+
|
19
|
+
def draw
|
20
|
+
Gosu.clip_to(@x, @y, @width, @height) do
|
21
|
+
Gosu.draw_quad(
|
22
|
+
@top_left.x, @top_left.y, @paint.top_left,
|
23
|
+
@top_right.x, @top_right.y, @paint.top_right,
|
24
|
+
@bottom_right.x, @bottom_right.y, @paint.bottom_right,
|
25
|
+
@bottom_left.x, @bottom_left.y, @paint.bottom_left,
|
26
|
+
@z
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
debug_outline if @debug
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
origin_x = (@x + (@width/2))
|
35
|
+
origin_y = (@y + (@height/2))
|
36
|
+
|
37
|
+
points = [
|
38
|
+
@top_left = Vector.new(@x, @y),
|
39
|
+
@top_right = Vector.new(@x + @width, @y),
|
40
|
+
@bottom_left = Vector.new(@x, @y + @height),
|
41
|
+
@bottom_right = Vector.new(@x + @width, @y + @height)
|
42
|
+
]
|
43
|
+
|
44
|
+
[@top_left, @top_right, @bottom_left, @bottom_right].each do |vector|
|
45
|
+
temp_x = vector.x - origin_x
|
46
|
+
temp_y = vector.y - origin_y
|
47
|
+
|
48
|
+
# 90 is up here, while gosu uses 0 for up.
|
49
|
+
radians = (@angle + 90).gosu_to_radians
|
50
|
+
vector.x = (@x + (@width/2)) + ((temp_x * Math.cos(radians)) - (temp_y * Math.sin(radians)))
|
51
|
+
vector.y = (@y + (@height/2)) + ((temp_x * Math.sin(radians)) + (temp_y * Math.cos(radians)))
|
52
|
+
end
|
53
|
+
|
54
|
+
# [
|
55
|
+
# [:top, @top_left, @top_right],
|
56
|
+
# [:right, @top_right, @bottom_right],
|
57
|
+
# [:bottom, @bottom_right, @bottom_left],
|
58
|
+
# [:left, @bottom_left, @top_left]
|
59
|
+
# ].each do |edge|
|
60
|
+
# points.each do |point|
|
61
|
+
# puts "#{edge.first} -> #{shortest_distance(point, edge[1], edge[2])}"
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
end
|
65
|
+
|
66
|
+
def shortest_distance(point, la, lb)
|
67
|
+
a = la.x - lb.x
|
68
|
+
b = la.y - lb.y
|
69
|
+
c = Gosu.distance(la.x, la.y, lb.x, lb.y)
|
70
|
+
p a,b,c
|
71
|
+
d = (a * point.x + b * point.y + c).abs / (Math.sqrt(a * a + b * b))
|
72
|
+
puts "Distance: #{d}"
|
73
|
+
exit!
|
74
|
+
return d
|
75
|
+
end
|
76
|
+
|
77
|
+
def debug_outline
|
78
|
+
# Top
|
79
|
+
Gosu.draw_line(
|
80
|
+
@x, @y, Gosu::Color::RED,
|
81
|
+
@x + @width, @y, Gosu::Color::RED,
|
82
|
+
@z
|
83
|
+
)
|
84
|
+
|
85
|
+
# Right
|
86
|
+
Gosu.draw_line(
|
87
|
+
@x + @width, @y, Gosu::Color::RED,
|
88
|
+
@x + @width, @y + @height, Gosu::Color::RED,
|
89
|
+
@z
|
90
|
+
)
|
91
|
+
|
92
|
+
# Bottom
|
93
|
+
Gosu.draw_line(
|
94
|
+
@x + @width, @y + @height, Gosu::Color::RED,
|
95
|
+
@x, @y + @height, Gosu::Color::RED,
|
96
|
+
@z
|
97
|
+
)
|
98
|
+
|
99
|
+
# Left
|
100
|
+
Gosu.draw_line(
|
101
|
+
@x, @y + @height, Gosu::Color::RED,
|
102
|
+
@x, @y, Gosu::Color::RED,
|
103
|
+
@z
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
def background=(_background)
|
108
|
+
@paint.set(_background)
|
109
|
+
update
|
110
|
+
end
|
111
|
+
|
112
|
+
def angle=(n)
|
113
|
+
@angle = n
|
114
|
+
update
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Paint
|
119
|
+
attr_accessor :top_left, :top_right, :bottom_left, :bottom_right
|
120
|
+
def initialize(background)
|
121
|
+
set(background)
|
122
|
+
end
|
123
|
+
|
124
|
+
def set(background)
|
125
|
+
@background = background
|
126
|
+
|
127
|
+
|
128
|
+
if background.is_a?(Numeric)
|
129
|
+
@top_left = background
|
130
|
+
@top_right = background
|
131
|
+
@bottom_left = background
|
132
|
+
@bottom_right = background
|
133
|
+
elsif background.is_a?(Gosu::Color)
|
134
|
+
@top_left = background
|
135
|
+
@top_right = background
|
136
|
+
@bottom_left = background
|
137
|
+
@bottom_right = background
|
138
|
+
elsif background.is_a?(Array)
|
139
|
+
if background.size == 1
|
140
|
+
set(background.first)
|
141
|
+
elsif background.size == 2
|
142
|
+
@top_left = background.first
|
143
|
+
@top_right = background.last
|
144
|
+
@bottom_left = background.first
|
145
|
+
@bottom_right = background.last
|
146
|
+
elsif background.size == 4
|
147
|
+
@top_left = background[0]
|
148
|
+
@top_right = background[1]
|
149
|
+
@bottom_left = background[2]
|
150
|
+
@bottom_right = background[3]
|
151
|
+
else
|
152
|
+
raise ArgumentError, "background array was empty or had wrong number of elements (expected 2 or 4 elements)"
|
153
|
+
end
|
154
|
+
elsif background.is_a?(Hash)
|
155
|
+
@top_left = background[:top_left]
|
156
|
+
@top_right = background[:top_right]
|
157
|
+
@bottom_left = background[:bottom_left]
|
158
|
+
@bottom_right = background[:bottom_right]
|
159
|
+
elsif background.is_a?(Range)
|
160
|
+
set([background.begin, background.begin, background.end, background.end])
|
161
|
+
else
|
162
|
+
raise ArgumentError, "background '#{background}' of type '#{background.class}' was not able to be processed"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Add <=> method to support Range based gradients
|
169
|
+
module Gosu
|
170
|
+
class Color
|
171
|
+
def <=>(other)
|
172
|
+
self
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -1,150 +1,150 @@
|
|
1
|
-
module CyberarmEngine
|
2
|
-
class BoundingBox
|
3
|
-
attr_accessor :min, :max
|
4
|
-
|
5
|
-
def initialize(*args)
|
6
|
-
case args.size
|
7
|
-
when 0
|
8
|
-
@min = Vector.new(0, 0, 0)
|
9
|
-
@max = Vector.new(0, 0, 0)
|
10
|
-
when 2
|
11
|
-
@min = args.first.clone
|
12
|
-
@max = args.last.clone
|
13
|
-
when 4
|
14
|
-
@min = Vector.new(args[0], args[1], 0)
|
15
|
-
@max = Vector.new(args[2], args[3], 0)
|
16
|
-
when 6
|
17
|
-
@min = Vector.new(args[0], args[1], args[2])
|
18
|
-
@max = Vector.new(args[3], args[4], args[5])
|
19
|
-
else
|
20
|
-
raise "Invalid number of arguments! Got: #{args.size}, expected: 0, 2, 4, or 6."
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def ==(other)
|
25
|
-
@min == other.min &&
|
26
|
-
@max == other.max
|
27
|
-
end
|
28
|
-
|
29
|
-
# returns a new bounding box that includes both bounding boxes
|
30
|
-
def union(other)
|
31
|
-
temp = BoundingBox.new
|
32
|
-
temp.min.x = [@min.x, other.min.x].min
|
33
|
-
temp.min.y = [@min.y, other.min.y].min
|
34
|
-
temp.min.z = [@min.z, other.min.z].min
|
35
|
-
|
36
|
-
temp.max.x = [@max.x, other.max.x].max
|
37
|
-
temp.max.y = [@max.y, other.max.y].max
|
38
|
-
temp.max.z = [@max.z, other.max.z].max
|
39
|
-
|
40
|
-
return temp
|
41
|
-
end
|
42
|
-
|
43
|
-
# returns the difference between both bounding boxes
|
44
|
-
def difference(other)
|
45
|
-
temp = BoundingBox.new
|
46
|
-
temp.min = @min - other.min
|
47
|
-
temp.max = @max - other.max
|
48
|
-
|
49
|
-
return temp
|
50
|
-
end
|
51
|
-
|
52
|
-
# returns whether bounding box intersects other
|
53
|
-
def intersect?(other)
|
54
|
-
if other.is_a?(Ray)
|
55
|
-
other.intersect?(self)
|
56
|
-
elsif other.is_a?(BoundingBox)
|
57
|
-
(@min.x <= other.max.x && @max.x >= other.min.x) &&
|
58
|
-
(@min.y <= other.max.y && @max.y >= other.min.y) &&
|
59
|
-
(@min.z <= other.max.z && @max.z >= other.min.z)
|
60
|
-
else
|
61
|
-
raise "Unknown collider: #{other.class}"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# does this bounding box envelop other bounding box? (inclusive of border)
|
66
|
-
def contains?(other)
|
67
|
-
other.min.x >= min.x && other.min.y >= min.y && other.min.z >= min.z &&
|
68
|
-
other.max.x <= max.x && other.max.y <= max.y && other.max.z <= max.z
|
69
|
-
end
|
70
|
-
|
71
|
-
# returns whether the 3D vector is inside of the bounding box
|
72
|
-
def inside?(vector)
|
73
|
-
(vector.x.between?(@min.x, @max.x) || vector.x.between?(@max.x, @min.x)) &&
|
74
|
-
(vector.y.between?(@min.y, @max.y) || vector.y.between?(@max.y, @min.y)) &&
|
75
|
-
(vector.z.between?(@min.z, @max.z) || vector.z.between?(@max.z, @min.z))
|
76
|
-
end
|
77
|
-
|
78
|
-
# returns whether the 2D vector is inside of the bounding box
|
79
|
-
def point?(vector)
|
80
|
-
(vector.x.between?(@min.x, @max.x) || vector.x.between?(@max.x, @min.x)) &&
|
81
|
-
(vector.y.between?(@min.y, @max.y) || vector.y.between?(@max.y, @min.y))
|
82
|
-
end
|
83
|
-
|
84
|
-
def volume
|
85
|
-
width * height * depth
|
86
|
-
end
|
87
|
-
|
88
|
-
def width
|
89
|
-
@max.x - @min.x
|
90
|
-
end
|
91
|
-
|
92
|
-
def height
|
93
|
-
@max.y - @min.y
|
94
|
-
end
|
95
|
-
|
96
|
-
def depth
|
97
|
-
@max.z - @min.z
|
98
|
-
end
|
99
|
-
|
100
|
-
def normalize(entity)
|
101
|
-
temp = BoundingBox.new
|
102
|
-
temp.min.x = @min.x.to_f * entity.scale.x
|
103
|
-
temp.min.y = @min.y.to_f * entity.scale.y
|
104
|
-
temp.min.z = @min.z.to_f * entity.scale.z
|
105
|
-
|
106
|
-
temp.max.x = @max.x.to_f * entity.scale.x
|
107
|
-
temp.max.y = @max.y.to_f * entity.scale.y
|
108
|
-
temp.max.z = @max.z.to_f * entity.scale.z
|
109
|
-
|
110
|
-
return temp
|
111
|
-
end
|
112
|
-
|
113
|
-
def normalize_with_offset(entity)
|
114
|
-
temp = BoundingBox.new
|
115
|
-
temp.min.x = @min.x.to_f * entity.scale.x + entity.position.x
|
116
|
-
temp.min.y = @min.y.to_f * entity.scale.y + entity.position.y
|
117
|
-
temp.min.z = @min.z.to_f * entity.scale.z + entity.position.z
|
118
|
-
|
119
|
-
temp.max.x = @max.x.to_f * entity.scale.x + entity.position.x
|
120
|
-
temp.max.y = @max.y.to_f * entity.scale.y + entity.position.y
|
121
|
-
temp.max.z = @max.z.to_f * entity.scale.z + entity.position.z
|
122
|
-
|
123
|
-
return temp
|
124
|
-
end
|
125
|
-
|
126
|
-
def +(other)
|
127
|
-
box = BoundingBox.new
|
128
|
-
box.min = self.min + other.min
|
129
|
-
box.min = self.max + other.max
|
130
|
-
|
131
|
-
return box
|
132
|
-
end
|
133
|
-
|
134
|
-
def -(other)
|
135
|
-
box = BoundingBox.new
|
136
|
-
box.min = self.min - other.min
|
137
|
-
box.min = self.max - other.max
|
138
|
-
|
139
|
-
return box
|
140
|
-
end
|
141
|
-
|
142
|
-
def sum
|
143
|
-
@min.sum + @max.sum
|
144
|
-
end
|
145
|
-
|
146
|
-
def clone
|
147
|
-
BoundingBox.new(@min.x, @min.y, @min.z, @max.x, @max.y, @max.z)
|
148
|
-
end
|
149
|
-
end
|
1
|
+
module CyberarmEngine
|
2
|
+
class BoundingBox
|
3
|
+
attr_accessor :min, :max
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
case args.size
|
7
|
+
when 0
|
8
|
+
@min = Vector.new(0, 0, 0)
|
9
|
+
@max = Vector.new(0, 0, 0)
|
10
|
+
when 2
|
11
|
+
@min = args.first.clone
|
12
|
+
@max = args.last.clone
|
13
|
+
when 4
|
14
|
+
@min = Vector.new(args[0], args[1], 0)
|
15
|
+
@max = Vector.new(args[2], args[3], 0)
|
16
|
+
when 6
|
17
|
+
@min = Vector.new(args[0], args[1], args[2])
|
18
|
+
@max = Vector.new(args[3], args[4], args[5])
|
19
|
+
else
|
20
|
+
raise "Invalid number of arguments! Got: #{args.size}, expected: 0, 2, 4, or 6."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def ==(other)
|
25
|
+
@min == other.min &&
|
26
|
+
@max == other.max
|
27
|
+
end
|
28
|
+
|
29
|
+
# returns a new bounding box that includes both bounding boxes
|
30
|
+
def union(other)
|
31
|
+
temp = BoundingBox.new
|
32
|
+
temp.min.x = [@min.x, other.min.x].min
|
33
|
+
temp.min.y = [@min.y, other.min.y].min
|
34
|
+
temp.min.z = [@min.z, other.min.z].min
|
35
|
+
|
36
|
+
temp.max.x = [@max.x, other.max.x].max
|
37
|
+
temp.max.y = [@max.y, other.max.y].max
|
38
|
+
temp.max.z = [@max.z, other.max.z].max
|
39
|
+
|
40
|
+
return temp
|
41
|
+
end
|
42
|
+
|
43
|
+
# returns the difference between both bounding boxes
|
44
|
+
def difference(other)
|
45
|
+
temp = BoundingBox.new
|
46
|
+
temp.min = @min - other.min
|
47
|
+
temp.max = @max - other.max
|
48
|
+
|
49
|
+
return temp
|
50
|
+
end
|
51
|
+
|
52
|
+
# returns whether bounding box intersects other
|
53
|
+
def intersect?(other)
|
54
|
+
if other.is_a?(Ray)
|
55
|
+
other.intersect?(self)
|
56
|
+
elsif other.is_a?(BoundingBox)
|
57
|
+
(@min.x <= other.max.x && @max.x >= other.min.x) &&
|
58
|
+
(@min.y <= other.max.y && @max.y >= other.min.y) &&
|
59
|
+
(@min.z <= other.max.z && @max.z >= other.min.z)
|
60
|
+
else
|
61
|
+
raise "Unknown collider: #{other.class}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# does this bounding box envelop other bounding box? (inclusive of border)
|
66
|
+
def contains?(other)
|
67
|
+
other.min.x >= min.x && other.min.y >= min.y && other.min.z >= min.z &&
|
68
|
+
other.max.x <= max.x && other.max.y <= max.y && other.max.z <= max.z
|
69
|
+
end
|
70
|
+
|
71
|
+
# returns whether the 3D vector is inside of the bounding box
|
72
|
+
def inside?(vector)
|
73
|
+
(vector.x.between?(@min.x, @max.x) || vector.x.between?(@max.x, @min.x)) &&
|
74
|
+
(vector.y.between?(@min.y, @max.y) || vector.y.between?(@max.y, @min.y)) &&
|
75
|
+
(vector.z.between?(@min.z, @max.z) || vector.z.between?(@max.z, @min.z))
|
76
|
+
end
|
77
|
+
|
78
|
+
# returns whether the 2D vector is inside of the bounding box
|
79
|
+
def point?(vector)
|
80
|
+
(vector.x.between?(@min.x, @max.x) || vector.x.between?(@max.x, @min.x)) &&
|
81
|
+
(vector.y.between?(@min.y, @max.y) || vector.y.between?(@max.y, @min.y))
|
82
|
+
end
|
83
|
+
|
84
|
+
def volume
|
85
|
+
width * height * depth
|
86
|
+
end
|
87
|
+
|
88
|
+
def width
|
89
|
+
@max.x - @min.x
|
90
|
+
end
|
91
|
+
|
92
|
+
def height
|
93
|
+
@max.y - @min.y
|
94
|
+
end
|
95
|
+
|
96
|
+
def depth
|
97
|
+
@max.z - @min.z
|
98
|
+
end
|
99
|
+
|
100
|
+
def normalize(entity)
|
101
|
+
temp = BoundingBox.new
|
102
|
+
temp.min.x = @min.x.to_f * entity.scale.x
|
103
|
+
temp.min.y = @min.y.to_f * entity.scale.y
|
104
|
+
temp.min.z = @min.z.to_f * entity.scale.z
|
105
|
+
|
106
|
+
temp.max.x = @max.x.to_f * entity.scale.x
|
107
|
+
temp.max.y = @max.y.to_f * entity.scale.y
|
108
|
+
temp.max.z = @max.z.to_f * entity.scale.z
|
109
|
+
|
110
|
+
return temp
|
111
|
+
end
|
112
|
+
|
113
|
+
def normalize_with_offset(entity)
|
114
|
+
temp = BoundingBox.new
|
115
|
+
temp.min.x = @min.x.to_f * entity.scale.x + entity.position.x
|
116
|
+
temp.min.y = @min.y.to_f * entity.scale.y + entity.position.y
|
117
|
+
temp.min.z = @min.z.to_f * entity.scale.z + entity.position.z
|
118
|
+
|
119
|
+
temp.max.x = @max.x.to_f * entity.scale.x + entity.position.x
|
120
|
+
temp.max.y = @max.y.to_f * entity.scale.y + entity.position.y
|
121
|
+
temp.max.z = @max.z.to_f * entity.scale.z + entity.position.z
|
122
|
+
|
123
|
+
return temp
|
124
|
+
end
|
125
|
+
|
126
|
+
def +(other)
|
127
|
+
box = BoundingBox.new
|
128
|
+
box.min = self.min + other.min
|
129
|
+
box.min = self.max + other.max
|
130
|
+
|
131
|
+
return box
|
132
|
+
end
|
133
|
+
|
134
|
+
def -(other)
|
135
|
+
box = BoundingBox.new
|
136
|
+
box.min = self.min - other.min
|
137
|
+
box.min = self.max - other.max
|
138
|
+
|
139
|
+
return box
|
140
|
+
end
|
141
|
+
|
142
|
+
def sum
|
143
|
+
@min.sum + @max.sum
|
144
|
+
end
|
145
|
+
|
146
|
+
def clone
|
147
|
+
BoundingBox.new(@min.x, @min.y, @min.z, @max.x, @max.y, @max.z)
|
148
|
+
end
|
149
|
+
end
|
150
150
|
end
|