cyberarm_engine 0.13.0 → 0.13.1

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 (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