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.
Files changed (44) 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 +43 -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 +47 -46
  12. data/lib/cyberarm_engine/animator.rb +54 -0
  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/engine.rb +101 -101
  17. data/lib/cyberarm_engine/game_object.rb +256 -256
  18. data/lib/cyberarm_engine/game_state.rb +88 -88
  19. data/lib/cyberarm_engine/gosu_ext/circle.rb +8 -8
  20. data/lib/cyberarm_engine/ray.rb +55 -55
  21. data/lib/cyberarm_engine/shader.rb +262 -205
  22. data/lib/cyberarm_engine/text.rb +146 -146
  23. data/lib/cyberarm_engine/timer.rb +22 -22
  24. data/lib/cyberarm_engine/transform.rb +272 -83
  25. data/lib/cyberarm_engine/ui/border_canvas.rb +100 -100
  26. data/lib/cyberarm_engine/ui/dsl.rb +98 -101
  27. data/lib/cyberarm_engine/ui/element.rb +275 -259
  28. data/lib/cyberarm_engine/ui/elements/button.rb +66 -66
  29. data/lib/cyberarm_engine/ui/elements/check_box.rb +58 -58
  30. data/lib/cyberarm_engine/ui/elements/container.rb +176 -162
  31. data/lib/cyberarm_engine/ui/elements/edit_line.rb +171 -102
  32. data/lib/cyberarm_engine/ui/elements/flow.rb +16 -16
  33. data/lib/cyberarm_engine/ui/elements/image.rb +51 -51
  34. data/lib/cyberarm_engine/ui/elements/label.rb +49 -49
  35. data/lib/cyberarm_engine/ui/elements/progress.rb +49 -49
  36. data/lib/cyberarm_engine/ui/elements/stack.rb +12 -12
  37. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +55 -55
  38. data/lib/cyberarm_engine/ui/event.rb +46 -45
  39. data/lib/cyberarm_engine/ui/gui_state.rb +134 -134
  40. data/lib/cyberarm_engine/ui/style.rb +36 -36
  41. data/lib/cyberarm_engine/ui/theme.rb +120 -119
  42. data/lib/cyberarm_engine/vector.rb +202 -198
  43. data/lib/cyberarm_engine/version.rb +4 -4
  44. metadata +6 -5
@@ -1,96 +1,96 @@
1
- module CyberarmEngine
2
- module Common
3
- def push_state(klass, options={})
4
- window.push_state(klass, options)
5
- end
6
-
7
- def current_state
8
- window.current_state
9
- end
10
-
11
- def previous_state
12
- window.previous_state
13
- end
14
-
15
- def pop_state
16
- window.pop_state
17
- end
18
-
19
- def show_cursor
20
- window.show_cursor
21
- end
22
-
23
- def show_cursor=boolean
24
- window.show_cursor = boolean
25
- end
26
-
27
- def draw_rect(x, y, width, height, color, z = 0)
28
- Gosu.draw_rect(x, y, width, height, color, z)
29
- end
30
-
31
- def fill(color, z = 0)
32
- draw_rect(0, 0, window.width, window.height, color, z)
33
- end
34
-
35
- def lighten(color, amount = 25)
36
- if defined?(color.alpha)
37
- return Gosu::Color.rgba(color.red + amount, color.green + amount, color.blue + amount, color.alpha)
38
- else
39
- return Gosu::Color.rgb(color.red + amount, color.green + amount, color.blue + amount)
40
- end
41
- end
42
-
43
- def darken(color, amount = 25)
44
- if defined?(color.alpha)
45
- return Gosu::Color.rgba(color.red - amount, color.green - amount, color.blue - amount, color.alpha)
46
- else
47
- return Gosu::Color.rgb(color.red - amount, color.green - amount, color.blue - amount)
48
- end
49
- end
50
-
51
- def opacity(color, ratio = 1.0)
52
- alpha = 255 * ratio
53
-
54
- return Gosu::Color.rgba(color.red, color.green, color.blue, alpha)
55
- end
56
-
57
- def get_asset(path, hash, klass, retro = false, tileable = false)
58
- asset = nil
59
- hash.detect do |_asset, instance|
60
- if _asset == path
61
- asset = instance
62
- true
63
- end
64
- end
65
-
66
- unless asset
67
- instance = nil
68
- if klass == Gosu::Image
69
- instance = klass.new(path, retro: retro, tileable: tileable)
70
- else
71
- instance = klass.new(path)
72
- end
73
- hash[path] = instance
74
- asset = instance
75
- end
76
-
77
- return asset
78
- end
79
-
80
- def get_image(path, retro: false, tileable: false)
81
- get_asset(path, Engine::IMAGES, Gosu::Image, retro, tileable)
82
- end
83
-
84
- def get_sample(path)
85
- get_asset(path, Engine::SAMPLES, Gosu::Sample)
86
- end
87
-
88
- def get_song(path)
89
- get_asset(path, Engine::SONGS, Gosu::Song)
90
- end
91
-
92
- def window
93
- $window
94
- end
95
- end
96
- end
1
+ module CyberarmEngine
2
+ module Common
3
+ def push_state(klass, options={})
4
+ window.push_state(klass, options)
5
+ end
6
+
7
+ def current_state
8
+ window.current_state
9
+ end
10
+
11
+ def previous_state
12
+ window.previous_state
13
+ end
14
+
15
+ def pop_state
16
+ window.pop_state
17
+ end
18
+
19
+ def show_cursor
20
+ window.show_cursor
21
+ end
22
+
23
+ def show_cursor=boolean
24
+ window.show_cursor = boolean
25
+ end
26
+
27
+ def draw_rect(x, y, width, height, color, z = 0)
28
+ Gosu.draw_rect(x, y, width, height, color, z)
29
+ end
30
+
31
+ def fill(color, z = 0)
32
+ draw_rect(0, 0, window.width, window.height, color, z)
33
+ end
34
+
35
+ def lighten(color, amount = 25)
36
+ if defined?(color.alpha)
37
+ return Gosu::Color.rgba(color.red + amount, color.green + amount, color.blue + amount, color.alpha)
38
+ else
39
+ return Gosu::Color.rgb(color.red + amount, color.green + amount, color.blue + amount)
40
+ end
41
+ end
42
+
43
+ def darken(color, amount = 25)
44
+ if defined?(color.alpha)
45
+ return Gosu::Color.rgba(color.red - amount, color.green - amount, color.blue - amount, color.alpha)
46
+ else
47
+ return Gosu::Color.rgb(color.red - amount, color.green - amount, color.blue - amount)
48
+ end
49
+ end
50
+
51
+ def opacity(color, ratio = 1.0)
52
+ alpha = 255 * ratio
53
+
54
+ return Gosu::Color.rgba(color.red, color.green, color.blue, alpha)
55
+ end
56
+
57
+ def get_asset(path, hash, klass, retro = false, tileable = false)
58
+ asset = nil
59
+ hash.detect do |_asset, instance|
60
+ if _asset == path
61
+ asset = instance
62
+ true
63
+ end
64
+ end
65
+
66
+ unless asset
67
+ instance = nil
68
+ if klass == Gosu::Image
69
+ instance = klass.new(path, retro: retro, tileable: tileable)
70
+ else
71
+ instance = klass.new(path)
72
+ end
73
+ hash[path] = instance
74
+ asset = instance
75
+ end
76
+
77
+ return asset
78
+ end
79
+
80
+ def get_image(path, retro: false, tileable: false)
81
+ get_asset(path, Engine::IMAGES, Gosu::Image, retro, tileable)
82
+ end
83
+
84
+ def get_sample(path)
85
+ get_asset(path, Engine::SAMPLES, Gosu::Sample)
86
+ end
87
+
88
+ def get_song(path)
89
+ get_asset(path, Engine::SONGS, Gosu::Song)
90
+ end
91
+
92
+ def window
93
+ $window
94
+ end
95
+ end
96
+ 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