gamebox 0.3.4 → 0.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. data/README.rdoc +38 -0
  2. data/Rakefile +1 -10
  3. data/TODO.txt +6 -6
  4. data/app_generators/gamebox_generator.rb +95 -0
  5. data/{lib/gamebox/templates/template_app → app_generators/templates}/.gitignore +0 -0
  6. data/app_generators/templates/Gemfile +7 -0
  7. data/app_generators/templates/NEXT_STEPS.txt +1 -0
  8. data/{lib/gamebox/templates/template_app/README → app_generators/templates/README.rdoc} +0 -0
  9. data/{lib/gamebox/templates/template_app → app_generators/templates}/Rakefile +0 -0
  10. data/{lib/gamebox/templates/template_app → app_generators/templates}/config/boot.rb +0 -0
  11. data/app_generators/templates/config/environment.rb +30 -0
  12. data/{lib/gamebox/templates/template_app → app_generators/templates}/config/game.yml +0 -0
  13. data/{lib/gamebox/templates/template_app → app_generators/templates}/data/fonts/FONTS_GO_HERE +0 -0
  14. data/{lib/gamebox/templates/template_app → app_generators/templates}/data/graphics/GRAPHICS_GO_HERE +0 -0
  15. data/{lib/gamebox/templates/template_app → app_generators/templates}/data/music/MUSIC_GOES_HERE +0 -0
  16. data/{lib/gamebox/templates/template_app → app_generators/templates}/data/sounds/SOUND_FX_GO_HERE +0 -0
  17. data/{lib/gamebox/templates → app_generators/templates/script}/actor.erb +0 -0
  18. data/{lib/gamebox/templates → app_generators/templates/script}/actor_spec.erb +0 -0
  19. data/{lib/gamebox/templates → app_generators/templates/script}/actor_view.erb +0 -0
  20. data/{lib/gamebox/templates → app_generators/templates/script}/actor_view_spec.erb +0 -0
  21. data/app_generators/templates/script/generate +12 -0
  22. data/{lib/gamebox/templates/template_app → app_generators/templates}/spec/helper.rb +0 -0
  23. data/app_generators/templates/src/actors/player.rb +8 -0
  24. data/{lib/gamebox/templates/template_app → app_generators/templates}/src/app.rb +0 -0
  25. data/app_generators/templates/src/demo_stage.rb +7 -0
  26. data/bin/gamebox +8 -70
  27. data/component_generators/actor_generator.rb +17 -0
  28. data/docs/CODE_REVIEW +1 -1
  29. data/docs/REFACTOR_NOTES.txt +25 -0
  30. data/docs/getting_started.rdoc +1 -1
  31. data/gamebox.gemspec +7 -4
  32. data/lib/gamebox.rb +6 -3
  33. data/lib/gamebox/actors/collidable_debugger.rb +13 -15
  34. data/lib/gamebox/actors/curtain.rb +44 -43
  35. data/lib/gamebox/actors/emitter.rb +3 -42
  36. data/lib/gamebox/actors/fps.rb +13 -6
  37. data/lib/gamebox/actors/label.rb +42 -34
  38. data/lib/gamebox/actors/logo.rb +2 -4
  39. data/lib/gamebox/actors/score.rb +37 -27
  40. data/lib/gamebox/actors/svg_actor.rb +45 -32
  41. data/lib/gamebox/behaviors/animated.rb +39 -59
  42. data/lib/gamebox/behaviors/audible.rb +14 -14
  43. data/lib/gamebox/behaviors/collidable.rb +65 -36
  44. data/lib/gamebox/behaviors/collidable/aabb_collidable.rb +2 -3
  45. data/lib/gamebox/behaviors/collidable/collidable_shape.rb +6 -4
  46. data/lib/gamebox/behaviors/collidable/polygon_collidable.rb +1 -1
  47. data/lib/gamebox/behaviors/emitting.rb +48 -0
  48. data/lib/gamebox/behaviors/graphical.rb +22 -56
  49. data/lib/gamebox/behaviors/layered.rb +8 -21
  50. data/lib/gamebox/behaviors/physical.rb +202 -213
  51. data/lib/gamebox/behaviors/positioned.rb +16 -0
  52. data/lib/gamebox/behaviors/projectile.rb +15 -0
  53. data/lib/gamebox/behaviors/visible.rb +16 -0
  54. data/lib/gamebox/core/aabb_helpers.rb +61 -0
  55. data/lib/gamebox/core/aabb_node.rb +118 -0
  56. data/lib/gamebox/core/aabb_tree.rb +137 -0
  57. data/lib/gamebox/core/actor.rb +102 -0
  58. data/lib/gamebox/core/actor_factory.rb +56 -0
  59. data/lib/gamebox/core/actor_view.rb +63 -0
  60. data/lib/gamebox/core/actor_view_factory.rb +40 -0
  61. data/lib/gamebox/{arbiter.rb → core/arbiter.rb} +31 -34
  62. data/lib/gamebox/{backstage.rb → core/backstage.rb} +0 -0
  63. data/lib/gamebox/core/behavior.rb +64 -0
  64. data/lib/gamebox/core/behavior_factory.rb +56 -0
  65. data/lib/gamebox/{class_finder.rb → core/class_finder.rb} +0 -0
  66. data/lib/gamebox/{config_manager.rb → core/config_manager.rb} +1 -1
  67. data/lib/gamebox/core/configuration.rb +39 -0
  68. data/lib/gamebox/core/core.rb +30 -0
  69. data/lib/gamebox/core/deprecated.rb +15 -0
  70. data/lib/gamebox/{director.rb → core/director.rb} +6 -11
  71. data/lib/gamebox/core/font_style.rb +26 -0
  72. data/lib/gamebox/core/font_style_factory.rb +11 -0
  73. data/lib/gamebox/core/game.rb +19 -0
  74. data/lib/gamebox/{hooked_gosu_window.rb → core/hooked_gosu_window.rb} +12 -6
  75. data/lib/gamebox/{input_manager.rb → core/input_manager.rb} +106 -99
  76. data/lib/gamebox/core/physics.rb +22 -0
  77. data/lib/gamebox/{physical_stage.rb → core/physics_manager.rb} +36 -30
  78. data/lib/gamebox/{resource_manager.rb → core/resource_manager.rb} +19 -18
  79. data/lib/gamebox/{sound_manager.rb → core/sound_manager.rb} +9 -7
  80. data/lib/gamebox/{stage.rb → core/stage.rb} +42 -80
  81. data/lib/gamebox/{stage_manager.rb → core/stage_manager.rb} +46 -53
  82. data/lib/gamebox/{stagehand.rb → core/stagehand.rb} +0 -0
  83. data/lib/gamebox/{svg_document.rb → core/svg_document.rb} +0 -0
  84. data/lib/gamebox/core/timer_manager.rb +50 -0
  85. data/lib/gamebox/{viewport.rb → core/viewport.rb} +2 -3
  86. data/lib/gamebox/{wrapped_screen.rb → core/wrapped_screen.rb} +12 -19
  87. data/lib/gamebox/gamebox_application.rb +7 -15
  88. data/lib/gamebox/lib/evented_attributes.rb +51 -0
  89. data/lib/gamebox/{ftor.rb → lib/ftor.rb} +0 -0
  90. data/lib/gamebox/lib/min_max_helpers.rb +10 -0
  91. data/lib/gamebox/lib/rect.rb +112 -54
  92. data/lib/gamebox/lib/yoda.rb +46 -0
  93. data/lib/gamebox/spec/helper.rb +317 -12
  94. data/lib/gamebox/stagehands/spatial_tree_stagehand.rb +61 -0
  95. data/lib/gamebox/version.rb +8 -3
  96. data/lib/gamebox/views/graphical_actor_view.rb +22 -29
  97. data/script/perf_aabb.rb +56 -0
  98. data/script/perf_array_access.rb +16 -0
  99. data/script/perf_collisions.rb +37 -18
  100. data/script/perf_struct_vs_array.rb +7 -7
  101. data/spec/acceptance/animation_spec.rb +65 -0
  102. data/spec/acceptance/basic_actor_lifecycle_spec.rb +92 -0
  103. data/spec/acceptance/built_in_collision_handling_spec.rb +55 -0
  104. data/spec/acceptance/chipmunk_collision_handling_spec.rb +83 -0
  105. data/spec/acceptance/fps_actor_spec.rb +40 -0
  106. data/spec/acceptance/pausing_spec.rb +61 -0
  107. data/spec/acceptance/timer_usage_spec.rb +53 -0
  108. data/spec/actors/emitter_spec.rb +5 -0
  109. data/spec/{label_spec.rb → actors/label_spec.rb} +1 -1
  110. data/spec/behaviors/animated_spec.rb +85 -0
  111. data/spec/behaviors/collidable_spec.rb +134 -0
  112. data/spec/{physical_spec.rb → behaviors/physical_spec.rb} +2 -1
  113. data/spec/behaviors/positioned_spec.rb +6 -0
  114. data/spec/behaviors/projectile_spec.rb +6 -0
  115. data/spec/core/aabb_tree_spec.rb +109 -0
  116. data/spec/core/actor_factory_spec.rb +44 -0
  117. data/spec/core/actor_spec.rb +78 -0
  118. data/spec/core/actor_view_spec.rb +53 -0
  119. data/spec/{arbiter_spec.rb → core/arbiter_spec.rb} +29 -30
  120. data/spec/core/backstage_spec.rb +37 -0
  121. data/spec/core/behavior_factory_spec.rb +50 -0
  122. data/spec/core/behavior_spec.rb +8 -0
  123. data/spec/core/configuration_spec.rb +8 -0
  124. data/spec/core/core_spec.rb +13 -0
  125. data/spec/core/font_style_factory_spec.rb +17 -0
  126. data/spec/core/font_style_spec.rb +41 -0
  127. data/spec/core/hooked_gosu_window_spec.rb +75 -0
  128. data/spec/core/input_manager_spec.rb +285 -0
  129. data/spec/core/physics_manager_spec.rb +11 -0
  130. data/spec/core/resource_manager_spec.rb +12 -0
  131. data/spec/core/stage_manager_spec.rb +140 -0
  132. data/spec/core/stage_spec.rb +73 -0
  133. data/spec/core/timer_manager_spec.rb +89 -0
  134. data/spec/{viewport_spec.rb → core/viewport_spec.rb} +6 -3
  135. data/spec/core/wrapped_screen_spec.rb +26 -0
  136. data/spec/fixtures/game.yml +7 -0
  137. data/spec/fixtures/snelpling/idle/1.png +0 -0
  138. data/spec/fixtures/snelpling/jump/1.png +0 -0
  139. data/spec/fixtures/snelpling/jump/2.png +0 -0
  140. data/spec/fixtures/snelpling/jump/3.png +0 -0
  141. data/spec/helper.rb +8 -0
  142. data/spec/{class_finder_spec.rb → lib/class_finder_spec.rb} +2 -1
  143. data/spec/stagehands/spatial_tree_stagehand_spec.rb +19 -0
  144. data/spec/views/graphical_actor_view_spec.rb +116 -0
  145. metadata +343 -144
  146. data/README.txt +0 -34
  147. data/lib/gamebox/actor.rb +0 -179
  148. data/lib/gamebox/actor_factory.rb +0 -57
  149. data/lib/gamebox/actor_view.rb +0 -44
  150. data/lib/gamebox/actors/spatial_debugger.rb +0 -62
  151. data/lib/gamebox/behavior.rb +0 -70
  152. data/lib/gamebox/behaviors/timed.rb +0 -33
  153. data/lib/gamebox/behaviors/updatable.rb +0 -12
  154. data/lib/gamebox/console_app.rb +0 -41
  155. data/lib/gamebox/gamebox_generator.rb +0 -32
  156. data/lib/gamebox/generators/actor_generator.rb +0 -43
  157. data/lib/gamebox/generators/view_generator.rb +0 -42
  158. data/lib/gamebox/physical_director.rb +0 -17
  159. data/lib/gamebox/physics.rb +0 -32
  160. data/lib/gamebox/spatial_bucket.rb +0 -9
  161. data/lib/gamebox/spatial_hash.rb +0 -194
  162. data/lib/gamebox/spatial_stagehand.rb +0 -80
  163. data/lib/gamebox/templates/template_app/Gemfile +0 -6
  164. data/lib/gamebox/templates/template_app/config/environment.rb +0 -23
  165. data/lib/gamebox/templates/template_app/config/stage_config.yml +0 -2
  166. data/lib/gamebox/templates/template_app/script/generate +0 -7
  167. data/lib/gamebox/templates/template_app/src/demo_stage.rb +0 -11
  168. data/lib/gamebox/templates/template_app/src/game.rb +0 -19
  169. data/lib/gamebox/templates/template_app/src/my_actor.rb +0 -14
  170. data/script/perf_spatial_hash.rb +0 -64
  171. data/spec/actor_factory_spec.rb +0 -61
  172. data/spec/actor_spec.rb +0 -71
  173. data/spec/actor_view_spec.rb +0 -61
  174. data/spec/animated_spec.rb +0 -83
  175. data/spec/backstage_spec.rb +0 -45
  176. data/spec/behavior_spec.rb +0 -28
  177. data/spec/collidable_spec.rb +0 -135
  178. data/spec/emitter_spec.rb +0 -20
  179. data/spec/input_manager_spec.rb +0 -134
  180. data/spec/resource_manager_spec.rb +0 -13
  181. data/spec/spatial_hash_spec.rb +0 -119
  182. data/spec/spatial_stagehand_spec.rb +0 -93
  183. data/spec/stage_manager_spec.rb +0 -25
  184. data/spec/stage_spec.rb +0 -65
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ # stolen from mongoid gem
3
+ module Gamebox #:nodoc:
4
+ module Extensions #:nodoc:
5
+ module Object #:nodoc:
6
+
7
+ # This module behaves like the master jedi.
8
+ module Yoda #:nodoc:
9
+
10
+ # Do or do not, there is no try. -- Yoda.
11
+ #
12
+ # @example Do or do not.
13
+ # object.do_or_do_not(:use, "The Force")
14
+ #
15
+ # @param [ String, Symbol ] name The method name.
16
+ # @param [ Array ] *args The arguments.
17
+ #
18
+ # @return [ Object, nil ] The result of the method call or nil if the
19
+ # method does not exist.
20
+ #
21
+ # @since 2.0.0.rc.1
22
+ def do_or_do_not(name, *args)
23
+ return nil unless name
24
+ respond_to?(name) ? send(name, *args) : nil
25
+ end
26
+ alias yoda do_or_do_not
27
+
28
+ # You must unlearn what you have learned. -- Yoda
29
+ #
30
+ # @example You must perform this execution.
31
+ # object.you_must(:use, "The Force")
32
+ #
33
+ # @param [ String, Symbol ] name The method name.
34
+ # @param [ Array ] *args The arguments.
35
+ #
36
+ # @return [ Object, nil ] The result of the method call or nil if the
37
+ # method does not exist. Nil if the object is frozen.
38
+ #
39
+ # @since 2.2.1
40
+ def you_must(name, *args)
41
+ frozen? ? nil : do_or_do_not(name, *args)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,25 +1,330 @@
1
1
  # Helper methods and classes for writing specs for your gamebox application
2
+ # def log(*args)
3
+ # # nothing for specs!
4
+ # end
5
+ include Gamebox
6
+
2
7
  module GameboxSpecHelpers
8
+ module ClassMethods
9
+ def inject_mocks(*mock_names_array)
10
+ before { @_mocks_created = create_mocks(*mock_names_array) }
11
+ subject { described_class.new @_mocks_created }
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+
17
+ def create_actor(type=:actor, args={})
18
+ act = create_conjected_object type, nil, false
19
+ act.configure args.merge(actor_type: type)
20
+ act
21
+ end
22
+
23
+ def create_conjected_object(type, args={}, configure=true)
24
+ actor_klass = ClassFinder.find(type)
25
+ raise "Could not find actor class #{type}" unless actor_klass
26
+
27
+ mocks = create_mocks *actor_klass.object_definition.component_names
28
+ actor_klass.new(mocks).tap do |actor|
29
+ actor.configure args if configure
30
+ end
31
+ end
32
+
33
+ def create_actor_view(type=:actor_view, args={}, configure=true)
34
+ create_conjected_object type, args, configure
35
+ end
36
+
37
+ def create_mocks(*args)
38
+ {}.tap do |mocks|
39
+ args.each do |mock_name|
40
+ the_mock = instance_variable_get("@#{mock_name}")
41
+ the_mock ||= mock(mock_name.to_s)
42
+ instance_variable_set "@#{mock_name}", the_mock
43
+ mocks[mock_name.to_sym] = the_mock
44
+ end
45
+ end
46
+ end
47
+
48
+ def create_stub_everythings(*args)
49
+ {}.tap do |stubs|
50
+ args.each do |stub_name|
51
+ the_stub = stub_everything(stub_name.to_s)
52
+ instance_variable_set "@#{stub_name}", the_stub
53
+ stubs[stub_name.to_sym] = the_stub
54
+ end
55
+ end
56
+ end
57
+
58
+ def expects_event(target, event_name, expected_args)
59
+ args = []
60
+ target.when event_name do |*event_args|
61
+ args << event_args
62
+ end
63
+ yield
64
+ args.should == expected_args
65
+ end
66
+
67
+ def evented_stub(wrapped_object)
68
+ EventedStub.new wrapped_object
69
+ end
70
+ end
71
+
72
+ def self.included(base)
73
+ base.send :include, InstanceMethods
74
+ base.send :extend, ClassMethods
75
+ end
76
+ end
77
+
78
+ class EventedStub
79
+ extend Publisher
80
+ can_fire_anything
81
+ def initialize(object)
82
+ @inner_stub = object
83
+ end
84
+ def method_missing(name, *args)
85
+ @inner_stub.send name, *args
86
+ end
87
+ def fire(*args)
88
+ super
89
+ end
90
+ end
91
+
92
+ module GameboxAcceptanceSpecHelpers
93
+ class ::MockGosuWindow
94
+ include GosuWindowAPI
95
+ extend Publisher
96
+ can_fire :update, :draw, :button_down, :button_up
97
+
98
+ def initialize
99
+ @total_millis = 0
100
+ end
101
+
102
+ def update(millis)
103
+ @total_millis += millis
104
+ Gosu.stubs(:milliseconds).returns @total_millis
105
+ super()
106
+ end
107
+
108
+ def caption=(new_caption)
109
+ end
110
+ end
111
+
112
+
113
+ class ::TestingStage < Stage
114
+ attr_accessor :actors
115
+
116
+ def initialize
117
+ @actors = []
118
+ end
119
+
120
+ def create_actor(actor_type, *args)
121
+ super.tap do |act|
122
+ @actors << act
123
+ act.when :remove_me do
124
+ @actors.delete act
125
+ end
126
+ end
127
+ end
128
+
129
+ def update(time)
130
+ @physics_manager.update time if @physics_manager
131
+ super
132
+ end
133
+ end
134
+
135
+ module MockCalls
136
+ attr_accessor :calls
137
+ def method_missing(*args)
138
+ @calls << args
139
+ end
140
+
141
+ def _reset!
142
+ @calls = []
143
+ end
144
+ end
145
+
146
+ class ::MockImage
147
+ include MockCalls
148
+ attr_accessor :filename
149
+ def initialize(filename)
150
+ _reset!
151
+ @filename = filename
152
+ end
3
153
 
4
- def create_actor(type, args = {})
5
- InputManager.any_instance.stubs :setup
6
- basic_opts = {
7
- stage: @stage = stub_everything,
8
- input: @input_manager = InputManager.new(wrapped_screen: 'wrapped_screen', config_manager: 'config_manager'),
9
- sound: @sound_manager = stub_everything,
10
- director: @director = stub_everything,
11
- resources: @resource_manager = stub_everything,
12
- }.merge(args)
154
+ def width; 10; end
155
+ def height; 20; end
156
+ end
157
+
158
+ class ::MockFont
159
+ attr_accessor :name, :size, :calls
160
+ include MockCalls
161
+ def initialize(name, size)
162
+ _reset!
163
+ @name = name
164
+ @size = size
165
+ end
166
+ def text_width(text)
167
+ size * text.size
168
+ end
169
+ def height
170
+ size
171
+ end
172
+ end
173
+
174
+
175
+ class ::TestingGame < Game
176
+ construct_with *Game.object_definition.component_names
177
+ public *Game.object_definition.component_names
178
+
179
+ def configure
180
+ stage_manager.change_stage_to :testing
181
+ end
182
+
183
+ def stage(&blk)
184
+ stage_manager.current_stage.instance_eval &blk
185
+ end
186
+
187
+ def current_stage
188
+ stage_manager.current_stage
189
+ end
190
+
191
+ def actor(actor_type)
192
+ stage_manager.current_stage.actors.detect { |act| act.actor_type == actor_type }
193
+ end
194
+ end
195
+
196
+ module ClassMethods
197
+ end
198
+
199
+ module InstanceMethods
200
+ def mock_image(filename)
201
+ context = Conject.default_object_context
202
+ resource_manager = context[:resource_manager]
203
+ MockImage.new(filename).tap do |img|
204
+ resource_manager.stubs(:load_image).with(filename).returns(img)
205
+ end
206
+ end
207
+
208
+ def see_actor_drawn(actor_type)
209
+ act = game.actor(actor_type)
210
+ act.should be
211
+ end
212
+
213
+ def see_image_drawn(img)
214
+ img.calls.should_not be_empty
215
+ img.calls.first.first.should == :draw
216
+ img._reset!
217
+ end
218
+
219
+ def see_image_not_drawn(img)
220
+ img.calls.should be_empty
221
+ end
222
+
223
+ def see_text_drawn(text, opts)
224
+ font = opts[:in]
225
+ font.calls.should_not be_empty
226
+ font.calls.first.first.should == :draw
227
+ font._reset!
228
+ end
229
+
230
+ def mock_font(name, size)
231
+ context = Conject.default_object_context
232
+ resource_manager = context[:resource_manager]
233
+ MockFont.new(name, size).tap do |font|
234
+ resource_manager.stubs(:load_font).with(name, size).returns(font)
235
+ end
236
+ end
13
237
 
14
- klass = ClassFinder.find(type)
238
+ def see_stage_ivars(ivar_hash)
239
+ ivar_hash.each do |name, val|
240
+ game.current_stage.instance_variable_get("@#{name}").should == val
241
+ end
242
+ end
15
243
 
16
- raise "Could not find actor class #{type}" unless klass
244
+ def pause
245
+ game.current_stage.pause
246
+ end
17
247
 
18
- klass.new(basic_opts)
248
+ def unpause
249
+ game.current_stage.unpause
250
+ end
251
+
252
+ def see_actor_attrs(actor_type, attrs)
253
+ act = game.actor(actor_type)
254
+ act.should be
255
+ act.should have_attrs(attrs)
256
+ end
257
+
258
+ def update(time)
259
+ gosu.update time
260
+ end
261
+
262
+ def draw
263
+ gosu.draw
264
+ end
265
+
266
+ def release_key(button_id)
267
+ gosu.button_up button_id
268
+ end
269
+
270
+ def press_key(button_id)
271
+ gosu.button_down button_id
272
+ end
273
+
274
+ def game
275
+ context = Conject.default_object_context
276
+ @game ||= context[:testing_game].tap do |g|
277
+ g.configure
278
+ input_manager = context[:input_manager]
279
+ input_manager.register g
280
+ end
281
+ end
282
+
283
+ def gosu
284
+ @gosu ||= MockGosuWindow.new
285
+ end
286
+
19
287
  end
20
288
 
289
+ def self.included(base)
290
+ base.send :include, InstanceMethods
291
+ base.send :extend, ClassMethods
292
+
293
+ RSpec::Matchers.define :have_actor do |actor_type|
294
+ match do |game|
295
+ !game.stage_manager.current_stage.actors.detect { |act| act.actor_type == actor_type }.nil?
296
+ end
297
+ end
298
+
299
+ RSpec::Matchers.define :have_attrs do |expected_attributes|
300
+ match do |actor|
301
+ expected_attributes.each do |key, val|
302
+ actor.send(key).should == val
303
+ end
304
+ end
305
+ end
306
+ end
21
307
  end
22
308
 
23
309
  RSpec.configure do |configuration|
24
310
  configuration.include GameboxSpecHelpers
311
+ configuration.include GameboxAcceptanceSpecHelpers
312
+
313
+ configuration.before(:each) do
314
+ Conject.instance_variable_set(:@default_object_context, nil)
315
+ end
316
+
317
+ configuration.before(:each, acceptance: true) do
318
+ Gamebox.configure do |config|
319
+ config.config_path = "spec/fixtures/"
320
+ config.gfx_path = "spec/fixtures/"
321
+ config.fonts_path = "spec/fixtures/"
322
+ config.music_path = "spec/fixtures/"
323
+ config.sound_path = "spec/fixtures/"
324
+ config.stages = [:testing]
325
+ end
326
+
327
+ HookedGosuWindow.stubs(:new).returns(gosu)
328
+ end
25
329
  end
330
+
@@ -0,0 +1,61 @@
1
+ require 'forwardable'
2
+
3
+ class SpatialTreeStagehand < Stagehand
4
+ extend Forwardable
5
+ def_delegators :@tree, :calculate_bb, :to_s, :each, :collisions, :query, :valid?
6
+
7
+ attr_reader :moved_items
8
+
9
+ def setup
10
+ @dead_actors = {}
11
+ @moved_items = {}
12
+ @tree = AABBTree.new
13
+ end
14
+
15
+ def items
16
+ @tree.items.keys
17
+ end
18
+
19
+ def add(actor)
20
+ # TODO change these to one event? position_changed?
21
+ # item.when :width_changed do |old_w, new_w|
22
+ # item.when :height_changed do |old_h, new_h|
23
+
24
+ actor.when :position_changed do move actor end
25
+ actor.when :remove_me do
26
+ remove actor
27
+ end
28
+ @dead_actors.delete actor
29
+ if @tree.include? actor
30
+ @tree.update actor
31
+ else
32
+ @tree.insert actor
33
+ end
34
+ end
35
+
36
+ def remove(actor)
37
+ @dead_actors[actor] = actor
38
+ @moved_items.delete actor
39
+ raise "remove #{actor} #{__FILE__}" unless @tree.valid?
40
+ end
41
+
42
+ def move(actor)
43
+ @moved_items[actor] = actor
44
+ end
45
+
46
+ def reset
47
+ @dead_actors.keys.each do |actor|
48
+ @tree.remove actor
49
+ @moved_items.delete actor
50
+ actor.unsubscribe_all self
51
+ end
52
+
53
+ @moved_items.keys.each do |actor|
54
+ @tree.update actor
55
+ end
56
+
57
+ @moved_items = {}
58
+ @dead_actors = {}
59
+ end
60
+
61
+ end