cyberarm_engine 0.13.0 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.travis.yml +5 -5
  4. data/Gemfile +6 -6
  5. data/LICENSE.txt +21 -21
  6. data/README.md +73 -43
  7. data/Rakefile +10 -10
  8. data/bin/console +14 -14
  9. data/bin/setup +8 -8
  10. data/cyberarm_engine.gemspec +36 -36
  11. data/lib/cyberarm_engine.rb +49 -47
  12. data/lib/cyberarm_engine/animator.rb +53 -53
  13. data/lib/cyberarm_engine/background.rb +175 -175
  14. data/lib/cyberarm_engine/bounding_box.rb +149 -149
  15. data/lib/cyberarm_engine/common.rb +96 -96
  16. data/lib/cyberarm_engine/config_file.rb +46 -0
  17. data/lib/cyberarm_engine/engine.rb +101 -101
  18. data/lib/cyberarm_engine/game_object.rb +256 -256
  19. data/lib/cyberarm_engine/game_state.rb +88 -88
  20. data/lib/cyberarm_engine/gosu_ext/circle.rb +8 -8
  21. data/lib/cyberarm_engine/ray.rb +55 -55
  22. data/lib/cyberarm_engine/shader.rb +398 -262
  23. data/lib/cyberarm_engine/text.rb +146 -146
  24. data/lib/cyberarm_engine/timer.rb +22 -22
  25. data/lib/cyberarm_engine/transform.rb +272 -272
  26. data/lib/cyberarm_engine/ui/border_canvas.rb +100 -100
  27. data/lib/cyberarm_engine/ui/dsl.rb +98 -98
  28. data/lib/cyberarm_engine/ui/element.rb +275 -275
  29. data/lib/cyberarm_engine/ui/elements/button.rb +66 -66
  30. data/lib/cyberarm_engine/ui/elements/check_box.rb +58 -58
  31. data/lib/cyberarm_engine/ui/elements/container.rb +176 -176
  32. data/lib/cyberarm_engine/ui/elements/edit_line.rb +171 -171
  33. data/lib/cyberarm_engine/ui/elements/flow.rb +16 -16
  34. data/lib/cyberarm_engine/ui/elements/image.rb +51 -51
  35. data/lib/cyberarm_engine/ui/elements/label.rb +49 -49
  36. data/lib/cyberarm_engine/ui/elements/progress.rb +49 -49
  37. data/lib/cyberarm_engine/ui/elements/stack.rb +12 -12
  38. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +55 -55
  39. data/lib/cyberarm_engine/ui/event.rb +46 -46
  40. data/lib/cyberarm_engine/ui/gui_state.rb +134 -134
  41. data/lib/cyberarm_engine/ui/style.rb +36 -36
  42. data/lib/cyberarm_engine/ui/theme.rb +120 -120
  43. data/lib/cyberarm_engine/vector.rb +289 -202
  44. data/lib/cyberarm_engine/version.rb +4 -4
  45. metadata +3 -2
@@ -0,0 +1,46 @@
1
+ module CyberarmEngine
2
+ class ConfigFile
3
+ def initialize(file:)
4
+ @file = file
5
+
6
+ if File.exist?(@file)
7
+ deserialize
8
+ else
9
+ @data = {}
10
+ end
11
+ end
12
+
13
+ def []= *keys, value
14
+ last_key = keys.last
15
+
16
+ if keys.size == 1
17
+ hash = @data
18
+ else
19
+ keys.pop
20
+ hash = @data[keys.shift] ||= {}
21
+
22
+ keys.each do |key|
23
+ hash[key] ||= {}
24
+ end
25
+ end
26
+
27
+ hash[last_key] = value
28
+ end
29
+
30
+ def get(*keys)
31
+ @data.dig(*keys)
32
+ end
33
+
34
+ def serialize
35
+ JSON.dump(@data)
36
+ end
37
+
38
+ def deserialize
39
+ @data = JSON.parse(File.read(@file), symbolize_names: true)
40
+ end
41
+
42
+ def save!
43
+ File.open(@file, "w") { |f| f.write(serialize) }
44
+ end
45
+ end
46
+ end
@@ -1,101 +1,101 @@
1
- module CyberarmEngine
2
- class Engine < Gosu::Window
3
- IMAGES = {}
4
- SAMPLES= {}
5
- SONGS = {}
6
-
7
- attr_accessor :show_cursor
8
- attr_reader :last_frame_time
9
-
10
- def self.now
11
- Gosu.milliseconds
12
- end
13
-
14
- def self.dt
15
- $window.last_frame_time/1000.0
16
- end
17
-
18
- def initialize(width: 800, height: 600, fullscreen: false, update_interval: 1000.0/60, resizable: false)
19
- @show_cursor = false
20
-
21
- super(width, height, fullscreen: fullscreen, update_interval: update_interval, resizable: resizable)
22
- $window = self
23
- @last_frame_time = Gosu.milliseconds-1
24
- @current_frame_time = Gosu.milliseconds
25
- self.caption = "CyberarmEngine #{CyberarmEngine::VERSION} #{Gosu.language}"
26
-
27
- @states = []
28
-
29
- setup if defined?(setup)
30
- end
31
-
32
- def draw
33
- current_state.draw if current_state
34
- end
35
-
36
- def update
37
- current_state.update if current_state
38
- @last_frame_time = Gosu.milliseconds-@current_frame_time
39
- @current_frame_time = Gosu.milliseconds
40
- end
41
-
42
- def needs_cursor?
43
- @show_cursor
44
- end
45
-
46
- def dt
47
- @last_frame_time/1000.0
48
- end
49
-
50
- def button_down(id)
51
- super
52
- current_state.button_down(id) if current_state
53
- end
54
-
55
- def button_up(id)
56
- super
57
- current_state.button_up(id) if current_state
58
- end
59
-
60
- def push_state(klass, options={})
61
- options = {setup: true}.merge(options)
62
-
63
- if klass.instance_of?(klass.class) && defined?(klass.options)
64
- @states << klass
65
- klass.setup if options[:setup]
66
- else
67
- @states << klass.new(options) if child_of?(klass, GameState)
68
- @states << klass.new if child_of?(klass, Element::Container)
69
- current_state.setup if current_state.class == klass && options[:setup]
70
- end
71
- end
72
-
73
- private def child_of?(input, klass)
74
- input.ancestors.detect {|c| c == klass}
75
- end
76
-
77
- def current_state
78
- @states.last
79
- end
80
-
81
- def previous_state
82
- if @states.size > 1 && state = @states[@states.size-2]
83
- return state
84
- else
85
- return nil
86
- end
87
- end
88
-
89
- def pop_state
90
- @states.pop
91
- end
92
-
93
- # Sourced from https://gist.github.com/ippa/662583
94
- def draw_circle(cx,cy,r, z = 9999,color = Gosu::Color::GREEN, step = 10)
95
- 0.step(360, step) do |a1|
96
- a2 = a1 + step
97
- draw_line(cx + Gosu.offset_x(a1, r), cy + Gosu.offset_y(a1, r), color, cx + Gosu.offset_x(a2, r), cy + Gosu.offset_y(a2, r), color, z)
98
- end
99
- end
100
- end
101
- end
1
+ module CyberarmEngine
2
+ class Engine < Gosu::Window
3
+ IMAGES = {}
4
+ SAMPLES= {}
5
+ SONGS = {}
6
+
7
+ attr_accessor :show_cursor
8
+ attr_reader :last_frame_time
9
+
10
+ def self.now
11
+ Gosu.milliseconds
12
+ end
13
+
14
+ def self.dt
15
+ $window.last_frame_time/1000.0
16
+ end
17
+
18
+ def initialize(width: 800, height: 600, fullscreen: false, update_interval: 1000.0/60, resizable: false)
19
+ @show_cursor = false
20
+
21
+ super(width, height, fullscreen: fullscreen, update_interval: update_interval, resizable: resizable)
22
+ $window = self
23
+ @last_frame_time = Gosu.milliseconds-1
24
+ @current_frame_time = Gosu.milliseconds
25
+ self.caption = "CyberarmEngine #{CyberarmEngine::VERSION} #{Gosu.language}"
26
+
27
+ @states = []
28
+
29
+ setup if defined?(setup)
30
+ end
31
+
32
+ def draw
33
+ current_state.draw if current_state
34
+ end
35
+
36
+ def update
37
+ current_state.update if current_state
38
+ @last_frame_time = Gosu.milliseconds-@current_frame_time
39
+ @current_frame_time = Gosu.milliseconds
40
+ end
41
+
42
+ def needs_cursor?
43
+ @show_cursor
44
+ end
45
+
46
+ def dt
47
+ @last_frame_time/1000.0
48
+ end
49
+
50
+ def button_down(id)
51
+ super
52
+ current_state.button_down(id) if current_state
53
+ end
54
+
55
+ def button_up(id)
56
+ super
57
+ current_state.button_up(id) if current_state
58
+ end
59
+
60
+ def push_state(klass, options={})
61
+ options = {setup: true}.merge(options)
62
+
63
+ if klass.instance_of?(klass.class) && defined?(klass.options)
64
+ @states << klass
65
+ klass.setup if options[:setup]
66
+ else
67
+ @states << klass.new(options) if child_of?(klass, GameState)
68
+ @states << klass.new if child_of?(klass, Element::Container)
69
+ current_state.setup if current_state.class == klass && options[:setup]
70
+ end
71
+ end
72
+
73
+ private def child_of?(input, klass)
74
+ input.ancestors.detect {|c| c == klass}
75
+ end
76
+
77
+ def current_state
78
+ @states.last
79
+ end
80
+
81
+ def previous_state
82
+ if @states.size > 1 && state = @states[@states.size-2]
83
+ return state
84
+ else
85
+ return nil
86
+ end
87
+ end
88
+
89
+ def pop_state
90
+ @states.pop
91
+ end
92
+
93
+ # Sourced from https://gist.github.com/ippa/662583
94
+ def draw_circle(cx,cy,r, z = 9999,color = Gosu::Color::GREEN, step = 10)
95
+ 0.step(360, step) do |a1|
96
+ a2 = a1 + step
97
+ draw_line(cx + Gosu.offset_x(a1, r), cy + Gosu.offset_y(a1, r), color, cx + Gosu.offset_x(a2, r), cy + Gosu.offset_y(a2, r), color, z)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -1,257 +1,257 @@
1
- module CyberarmEngine
2
- class GameObject
3
- include Common
4
-
5
- attr_accessor :image, :angle, :position, :velocity, :center_x, :center_y, :scale_x, :scale_y,
6
- :color, :mode, :options, :paused, :radius, :last_position
7
- attr_reader :alpha
8
- def initialize(options={})
9
- if options[:auto_manage] || options[:auto_manage] == nil
10
- $window.current_state.add_game_object(self)
11
- end
12
-
13
- @options = options
14
- @image = options[:image] ? image(options[:image]) : nil
15
- x = options[:x] ? options[:x] : 0
16
- y = options[:y] ? options[:y] : 0
17
- z = options[:z] ? options[:z] : 0
18
- @position = Vector.new(x, y, z)
19
- @velocity = Vector.new
20
- @last_position = Vector.new
21
- @angle = options[:angle] ? options[:angle] : 0
22
-
23
- @center_x = options[:center_x] ? options[:center_x] : 0.5
24
- @center_y = options[:center_y] ? options[:center_y] : 0.5
25
-
26
- @scale_x = options[:scale_x] ? options[:scale_x] : 1
27
- @scale_y = options[:scale_y] ? options[:scale_y] : 1
28
-
29
- @color = options[:color] ? options[:color] : Gosu::Color.argb(0xff_ffffff)
30
- @alpha = options[:alpha] ? options[:alpha] : 255
31
- @mode = options[:mode] ? options[:mode] : :default
32
-
33
- @paused = false
34
- @speed = 0
35
- @debug_color = Gosu::Color::GREEN
36
- @world_center_point = Vector.new(0,0)
37
-
38
- setup
39
-
40
- @debug_text = Text.new("", color: @debug_color, y: @position.y-(self.height*self.scale), z: 9999)
41
- @debug_text.x = @position.x
42
- if @radius == 0 || @radius == nil
43
- @radius = options[:radius] ? options[:radius] : defined?(@image.width) ? ((@image.width+@image.height)/4)*scale : 1
44
- end
45
- end
46
-
47
- def draw
48
- if @image
49
- @image.draw_rot(@position.x, @position.y, @position.z, @angle, @center_x, @center_y, @scale_x, @scale_y, @color, @mode)
50
- end
51
-
52
- if $debug
53
- show_debug_heading
54
- $window.draw_circle(@position.x, @position.y, radius, 9999, @debug_color)
55
- if @debug_text.text != ""
56
- $window.draw_rect(@debug_text.x-10, (@debug_text.y-10), @debug_text.width+20, @debug_text.height+20, Gosu::Color.rgba(0,0,0,200), 9999)
57
- @debug_text.draw
58
- end
59
- end
60
- end
61
-
62
- def update
63
- end
64
-
65
- def debug_text(text)
66
- @debug_text.text = text
67
- @debug_text.x = @position.x-(@debug_text.width / 2)
68
- @debug_text.y = @position.y-(@debug_text.height + self.radius + self.height)
69
- end
70
-
71
- def scale
72
- if @scale_x == @scale_y
73
- return @scale_x
74
- else
75
- false
76
- # maths?
77
- end
78
- end
79
-
80
- def scale=(int)
81
- self.scale_x = int
82
- self.scale_y = int
83
- self.radius = ((@image.width+@image.height)/4)*self.scale
84
- end
85
-
86
- def visible
87
- true
88
- # if _x_visible
89
- # if _y_visible
90
- # true
91
- # else
92
- # false
93
- # end
94
- # else
95
- # false
96
- # end
97
- end
98
-
99
- def _x_visible
100
- self.x.between?(($window.width/2)-(@world_center_point.x), ($window.width/2)+@world_center_point.x) ||
101
- self.x.between?(((@world_center_point.x)-$window.width/2), ($window.width/2)+@world_center_point.x)
102
- end
103
-
104
- def _y_visible
105
- self.y.between?(($window.height/2)-(@world_center_point.y), ($window.height/2)+@world_center_point.y) ||
106
- self.y.between?((@world_center_point.y)-($window.height/2), ($window.height/2)+@world_center_point.y)
107
- end
108
-
109
- def heading(ahead_by = 100, object = nil, angle_only = false)
110
- direction = Gosu.angle(@last_position.x, @last_position.x, @position.x, position.y).gosu_to_radians
111
-
112
- _x = @position.x + (ahead_by * Math.cos(direction))
113
- _y = @position.y + (ahead_by * Math.sin(direction))
114
-
115
- return direction if angle_only
116
- return Vector.new(_x, _y) unless angle_only
117
- end
118
-
119
- def show_debug_heading
120
- _heading = heading
121
- Gosu.draw_line(@position.x, @position.y, @debug_color, _heading.x, _heading.y, @debug_color, 9999)
122
- end
123
-
124
- def width
125
- @image ? @image.width * self.scale : 0
126
- end
127
-
128
- def height
129
- @image ? @image.height * self.scale : 0
130
- end
131
-
132
- def pause
133
- @paused = true
134
- end
135
-
136
- def unpause
137
- @paused = false
138
- end
139
-
140
- def rotate(int)
141
- self.angle+=int
142
- self.angle%=360
143
- end
144
-
145
- def alpha=(int) # 0-255
146
- @alpha = int
147
- @alpha = 255 if @alpha > 255
148
- @color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, int)
149
- end
150
-
151
- def draw_rect(x, y, width, height, color, z = 0)
152
- $window.draw_rect(x,y,width,height,color,z)
153
- end
154
-
155
- def button_up(id)
156
- end
157
-
158
- def button_down(id)
159
- end
160
-
161
- def find_closest(game_object_class)
162
- best_object = nil
163
- best_distance = 100_000_000_000 # Huge default number
164
-
165
- game_object_class.all.each do |object|
166
- distance = Gosu::distance(self.x, self.y, object.x, object.y)
167
- if distance <= best_distance
168
- best_object = object
169
- best_distance = distance
170
- end
171
- end
172
-
173
- return best_object
174
- end
175
-
176
- def look_at(object)
177
- # TODO: Implement
178
- end
179
-
180
- def circle_collision?(object)
181
- distance = Gosu.distance(self.x, self.y, object.x, object.y)
182
- if distance <= self.radius+object.radius
183
- true
184
- else
185
- false
186
- end
187
- end
188
-
189
- # Duplication... so DRY.
190
- def each_circle_collision(object, resolve_with = :width, &block)
191
- if object.class != Class && object.instance_of?(object.class)
192
- $window.current_state.game_objects.select {|i| i.class == object.class}.each do |o|
193
- distance = Gosu.distance(self.x, self.y, object.x, object.y)
194
- if distance <= self.radius+object.radius
195
- block.call(o, object) if block
196
- end
197
- end
198
- else
199
- list = $window.current_state.game_objects.select {|i| i.class == object}
200
- list.each do |o|
201
- next if self == o
202
- distance = Gosu.distance(self.x, self.y, o.x, o.y)
203
- if distance <= self.radius+o.radius
204
- block.call(self, o) if block
205
- end
206
- end
207
- end
208
- end
209
-
210
- def destroy
211
- if $window.current_state
212
- $window.current_state.game_objects.each do |o|
213
- if o.is_a?(self.class) && o == self
214
- $window.current_state.game_objects.delete(o)
215
- end
216
- end
217
- end
218
- end
219
-
220
- # NOTE: This could be implemented more reliably
221
- def all
222
- INSTANCES.select {|i| i.class == self}
223
- end
224
-
225
- def self.each_circle_collision(object, resolve_with = :width, &block)
226
- if object.class != Class && object.instance_of?(object.class)
227
- $window.current_state.game_objects.select {|i| i.class == self}.each do |o|
228
- distance = Gosu.distance(o.x, o.y, object.x, object.y)
229
- if distance <= o.radius+object.radius
230
- block.call(o, object) if block
231
- end
232
- end
233
- else
234
- lista = $window.current_state.game_objects.select {|i| i.class == self}
235
- listb = $window.current_state.game_objects.select {|i| i.class == object}
236
- lista.product(listb).each do |o, o2|
237
- next if o == o2
238
- distance = Gosu.distance(o.x, o.y, o2.x, o2.y)
239
- if distance <= o.radius+o2.radius
240
- block.call(o, o2) if block
241
- end
242
- end
243
- end
244
- end
245
-
246
- def self.destroy_all
247
- INSTANCES.clear
248
- if $window.current_state
249
- $window.current_state.game_objects.each do |o|
250
- if o.is_a?(self.class)
251
- $window.current_state.game_objects.delete(o)
252
- end
253
- end
254
- end
255
- end
256
- end
1
+ module CyberarmEngine
2
+ class GameObject
3
+ include Common
4
+
5
+ attr_accessor :image, :angle, :position, :velocity, :center_x, :center_y, :scale_x, :scale_y,
6
+ :color, :mode, :options, :paused, :radius, :last_position
7
+ attr_reader :alpha
8
+ def initialize(options={})
9
+ if options[:auto_manage] || options[:auto_manage] == nil
10
+ $window.current_state.add_game_object(self)
11
+ end
12
+
13
+ @options = options
14
+ @image = options[:image] ? image(options[:image]) : nil
15
+ x = options[:x] ? options[:x] : 0
16
+ y = options[:y] ? options[:y] : 0
17
+ z = options[:z] ? options[:z] : 0
18
+ @position = Vector.new(x, y, z)
19
+ @velocity = Vector.new
20
+ @last_position = Vector.new
21
+ @angle = options[:angle] ? options[:angle] : 0
22
+
23
+ @center_x = options[:center_x] ? options[:center_x] : 0.5
24
+ @center_y = options[:center_y] ? options[:center_y] : 0.5
25
+
26
+ @scale_x = options[:scale_x] ? options[:scale_x] : 1
27
+ @scale_y = options[:scale_y] ? options[:scale_y] : 1
28
+
29
+ @color = options[:color] ? options[:color] : Gosu::Color.argb(0xff_ffffff)
30
+ @alpha = options[:alpha] ? options[:alpha] : 255
31
+ @mode = options[:mode] ? options[:mode] : :default
32
+
33
+ @paused = false
34
+ @speed = 0
35
+ @debug_color = Gosu::Color::GREEN
36
+ @world_center_point = Vector.new(0,0)
37
+
38
+ setup
39
+
40
+ @debug_text = Text.new("", color: @debug_color, y: @position.y-(self.height*self.scale), z: 9999)
41
+ @debug_text.x = @position.x
42
+ if @radius == 0 || @radius == nil
43
+ @radius = options[:radius] ? options[:radius] : defined?(@image.width) ? ((@image.width+@image.height)/4)*scale : 1
44
+ end
45
+ end
46
+
47
+ def draw
48
+ if @image
49
+ @image.draw_rot(@position.x, @position.y, @position.z, @angle, @center_x, @center_y, @scale_x, @scale_y, @color, @mode)
50
+ end
51
+
52
+ if $debug
53
+ show_debug_heading
54
+ $window.draw_circle(@position.x, @position.y, radius, 9999, @debug_color)
55
+ if @debug_text.text != ""
56
+ $window.draw_rect(@debug_text.x-10, (@debug_text.y-10), @debug_text.width+20, @debug_text.height+20, Gosu::Color.rgba(0,0,0,200), 9999)
57
+ @debug_text.draw
58
+ end
59
+ end
60
+ end
61
+
62
+ def update
63
+ end
64
+
65
+ def debug_text(text)
66
+ @debug_text.text = text
67
+ @debug_text.x = @position.x-(@debug_text.width / 2)
68
+ @debug_text.y = @position.y-(@debug_text.height + self.radius + self.height)
69
+ end
70
+
71
+ def scale
72
+ if @scale_x == @scale_y
73
+ return @scale_x
74
+ else
75
+ false
76
+ # maths?
77
+ end
78
+ end
79
+
80
+ def scale=(int)
81
+ self.scale_x = int
82
+ self.scale_y = int
83
+ self.radius = ((@image.width+@image.height)/4)*self.scale
84
+ end
85
+
86
+ def visible
87
+ true
88
+ # if _x_visible
89
+ # if _y_visible
90
+ # true
91
+ # else
92
+ # false
93
+ # end
94
+ # else
95
+ # false
96
+ # end
97
+ end
98
+
99
+ def _x_visible
100
+ self.x.between?(($window.width/2)-(@world_center_point.x), ($window.width/2)+@world_center_point.x) ||
101
+ self.x.between?(((@world_center_point.x)-$window.width/2), ($window.width/2)+@world_center_point.x)
102
+ end
103
+
104
+ def _y_visible
105
+ self.y.between?(($window.height/2)-(@world_center_point.y), ($window.height/2)+@world_center_point.y) ||
106
+ self.y.between?((@world_center_point.y)-($window.height/2), ($window.height/2)+@world_center_point.y)
107
+ end
108
+
109
+ def heading(ahead_by = 100, object = nil, angle_only = false)
110
+ direction = Gosu.angle(@last_position.x, @last_position.x, @position.x, position.y).gosu_to_radians
111
+
112
+ _x = @position.x + (ahead_by * Math.cos(direction))
113
+ _y = @position.y + (ahead_by * Math.sin(direction))
114
+
115
+ return direction if angle_only
116
+ return Vector.new(_x, _y) unless angle_only
117
+ end
118
+
119
+ def show_debug_heading
120
+ _heading = heading
121
+ Gosu.draw_line(@position.x, @position.y, @debug_color, _heading.x, _heading.y, @debug_color, 9999)
122
+ end
123
+
124
+ def width
125
+ @image ? @image.width * self.scale : 0
126
+ end
127
+
128
+ def height
129
+ @image ? @image.height * self.scale : 0
130
+ end
131
+
132
+ def pause
133
+ @paused = true
134
+ end
135
+
136
+ def unpause
137
+ @paused = false
138
+ end
139
+
140
+ def rotate(int)
141
+ self.angle+=int
142
+ self.angle%=360
143
+ end
144
+
145
+ def alpha=(int) # 0-255
146
+ @alpha = int
147
+ @alpha = 255 if @alpha > 255
148
+ @color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, int)
149
+ end
150
+
151
+ def draw_rect(x, y, width, height, color, z = 0)
152
+ $window.draw_rect(x,y,width,height,color,z)
153
+ end
154
+
155
+ def button_up(id)
156
+ end
157
+
158
+ def button_down(id)
159
+ end
160
+
161
+ def find_closest(game_object_class)
162
+ best_object = nil
163
+ best_distance = 100_000_000_000 # Huge default number
164
+
165
+ game_object_class.all.each do |object|
166
+ distance = Gosu::distance(self.x, self.y, object.x, object.y)
167
+ if distance <= best_distance
168
+ best_object = object
169
+ best_distance = distance
170
+ end
171
+ end
172
+
173
+ return best_object
174
+ end
175
+
176
+ def look_at(object)
177
+ # TODO: Implement
178
+ end
179
+
180
+ def circle_collision?(object)
181
+ distance = Gosu.distance(self.x, self.y, object.x, object.y)
182
+ if distance <= self.radius+object.radius
183
+ true
184
+ else
185
+ false
186
+ end
187
+ end
188
+
189
+ # Duplication... so DRY.
190
+ def each_circle_collision(object, resolve_with = :width, &block)
191
+ if object.class != Class && object.instance_of?(object.class)
192
+ $window.current_state.game_objects.select {|i| i.class == object.class}.each do |o|
193
+ distance = Gosu.distance(self.x, self.y, object.x, object.y)
194
+ if distance <= self.radius+object.radius
195
+ block.call(o, object) if block
196
+ end
197
+ end
198
+ else
199
+ list = $window.current_state.game_objects.select {|i| i.class == object}
200
+ list.each do |o|
201
+ next if self == o
202
+ distance = Gosu.distance(self.x, self.y, o.x, o.y)
203
+ if distance <= self.radius+o.radius
204
+ block.call(self, o) if block
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ def destroy
211
+ if $window.current_state
212
+ $window.current_state.game_objects.each do |o|
213
+ if o.is_a?(self.class) && o == self
214
+ $window.current_state.game_objects.delete(o)
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ # NOTE: This could be implemented more reliably
221
+ def all
222
+ INSTANCES.select {|i| i.class == self}
223
+ end
224
+
225
+ def self.each_circle_collision(object, resolve_with = :width, &block)
226
+ if object.class != Class && object.instance_of?(object.class)
227
+ $window.current_state.game_objects.select {|i| i.class == self}.each do |o|
228
+ distance = Gosu.distance(o.x, o.y, object.x, object.y)
229
+ if distance <= o.radius+object.radius
230
+ block.call(o, object) if block
231
+ end
232
+ end
233
+ else
234
+ lista = $window.current_state.game_objects.select {|i| i.class == self}
235
+ listb = $window.current_state.game_objects.select {|i| i.class == object}
236
+ lista.product(listb).each do |o, o2|
237
+ next if o == o2
238
+ distance = Gosu.distance(o.x, o.y, o2.x, o2.y)
239
+ if distance <= o.radius+o2.radius
240
+ block.call(o, o2) if block
241
+ end
242
+ end
243
+ end
244
+ end
245
+
246
+ def self.destroy_all
247
+ INSTANCES.clear
248
+ if $window.current_state
249
+ $window.current_state.game_objects.each do |o|
250
+ if o.is_a?(self.class)
251
+ $window.current_state.game_objects.delete(o)
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
257
257
  end