gamebox 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +9 -0
  3. data/History.txt +5 -0
  4. data/README.txt +4 -3
  5. data/Rakefile +12 -4
  6. data/TODO.txt +1 -5
  7. data/VERSION +1 -1
  8. data/docs/getting_started.rdoc +2 -2
  9. data/gamebox.gemspec +26 -10
  10. data/lib/gamebox/actor.rb +10 -3
  11. data/lib/gamebox/actor_factory.rb +2 -2
  12. data/lib/gamebox/actor_view.rb +14 -11
  13. data/lib/gamebox/actors/collidable_debugger.rb +35 -0
  14. data/lib/gamebox/actors/curtain.rb +2 -2
  15. data/lib/gamebox/actors/logo.rb +0 -6
  16. data/lib/gamebox/actors/score.rb +2 -5
  17. data/lib/gamebox/actors/spatial_debugger.rb +47 -0
  18. data/lib/gamebox/actors/svg_actor.rb +4 -6
  19. data/lib/gamebox/arbiter.rb +108 -15
  20. data/lib/gamebox/behavior.rb +29 -1
  21. data/lib/gamebox/behaviors/animated.rb +14 -23
  22. data/lib/gamebox/behaviors/audible.rb +1 -12
  23. data/lib/gamebox/behaviors/collidable.rb +29 -22
  24. data/lib/gamebox/behaviors/collidable/aabb_collidable.rb +61 -0
  25. data/lib/gamebox/behaviors/collidable/circle_collidable.rb +17 -0
  26. data/lib/gamebox/behaviors/collidable/collidable_shape.rb +35 -0
  27. data/lib/gamebox/behaviors/collidable/polygon_collidable.rb +85 -0
  28. data/lib/gamebox/behaviors/graphical.rb +13 -10
  29. data/lib/gamebox/behaviors/layered.rb +6 -20
  30. data/lib/gamebox/behaviors/physical.rb +116 -93
  31. data/lib/gamebox/class_finder.rb +6 -2
  32. data/lib/gamebox/config_manager.rb +24 -4
  33. data/lib/gamebox/data/config/objects.yml +5 -3
  34. data/lib/gamebox/ftor.rb +372 -0
  35. data/lib/gamebox/gamebox_application.rb +2 -8
  36. data/lib/gamebox/hooked_gosu_window.rb +30 -0
  37. data/lib/gamebox/input_manager.rb +78 -79
  38. data/lib/gamebox/lib/code_statistics.rb +1 -1
  39. data/lib/gamebox/lib/numbers_ext.rb +1 -1
  40. data/lib/gamebox/lib/rect.rb +612 -0
  41. data/lib/gamebox/physical_stage.rb +12 -2
  42. data/lib/gamebox/physics.rb +14 -3
  43. data/lib/gamebox/resource_manager.rb +28 -65
  44. data/lib/gamebox/sound_manager.rb +7 -13
  45. data/lib/gamebox/spatial_hash.rb +60 -14
  46. data/lib/gamebox/spatial_stagehand.rb +19 -0
  47. data/lib/gamebox/stage.rb +16 -1
  48. data/lib/gamebox/stage_manager.rb +1 -1
  49. data/lib/gamebox/svg_document.rb +1 -0
  50. data/lib/gamebox/tasks/gamebox_tasks.rb +23 -11
  51. data/lib/gamebox/templates/template_app/.gitignore +1 -0
  52. data/lib/gamebox/templates/template_app/Gemfile +1 -1
  53. data/lib/gamebox/templates/template_app/Rakefile +6 -21
  54. data/lib/gamebox/templates/template_app/config/environment.rb +14 -0
  55. data/lib/gamebox/templates/template_app/config/game.yml +2 -1
  56. data/lib/gamebox/templates/template_app/script/generate +0 -3
  57. data/lib/gamebox/templates/template_app/src/demo_stage.rb +1 -11
  58. data/lib/gamebox/templates/template_app/src/game.rb +0 -1
  59. data/lib/gamebox/templates/template_app/src/my_actor.rb +2 -2
  60. data/lib/gamebox/version.rb +1 -1
  61. data/lib/gamebox/views/graphical_actor_view.rb +15 -9
  62. data/lib/gamebox/wrapped_screen.rb +114 -7
  63. data/load_paths.rb +20 -0
  64. data/script/perf_spatial_hash.rb +73 -0
  65. data/spec/actor_view_spec.rb +1 -1
  66. data/spec/arbiter_spec.rb +264 -0
  67. data/spec/behavior_spec.rb +19 -2
  68. data/spec/collidable_spec.rb +105 -5
  69. data/spec/helper.rb +1 -1
  70. data/spec/label_spec.rb +1 -1
  71. data/spec/resource_manager_spec.rb +1 -1
  72. data/spec/spatial_hash_spec.rb +1 -1
  73. metadata +52 -10
  74. data/lib/gamebox/lib/surface_ext.rb +0 -76
@@ -4,7 +4,7 @@ require 'actor_view'
4
4
  describe 'A new actor view' do
5
5
 
6
6
  it 'should be layered 0/1 by default' do
7
- @test_me = ActorView.new :stage, Actor.new({})
7
+ @test_me = ActorView.new :stage, Actor.new({}), :wrapped_screen
8
8
  @test_me.layer.should == 0
9
9
  @test_me.parallax.should == 1
10
10
  end
@@ -0,0 +1,264 @@
1
+ require File.join(File.dirname(__FILE__),'helper')
2
+ require 'arbiter'
3
+
4
+ class Arb
5
+ include Arbiter
6
+ end
7
+
8
+ describe 'Arbiter' do
9
+
10
+ before do
11
+ @arbiter = Arb.new
12
+ end
13
+
14
+ it 'should construct' do
15
+ @arbiter.should_not be_nil
16
+ end
17
+
18
+ describe '#center_x' do
19
+ it 'should return the center x for circle'
20
+ it 'should return the center x for aabb'
21
+ it 'should return the center x for polygon'
22
+ end
23
+
24
+ describe '#center_y' do
25
+ it 'should return the center y for circle'
26
+ it 'should return the center y for aabb'
27
+ it 'should return the center y for polygon'
28
+ end
29
+
30
+ describe '#collide?' do
31
+ it 'should call the correct circle circle collision method' do
32
+ a = stub(:collidable_shape => :circle)
33
+ b = stub(:collidable_shape => :circle)
34
+ @arbiter.should_receive(:collide_circle_circle?).with(a,b).and_return(true)
35
+
36
+ @arbiter.collide?(a,b).should be_true
37
+ end
38
+
39
+ it 'should call the correct circle polygon collision method' do
40
+ a = stub(:collidable_shape => :circle)
41
+ b = stub(:collidable_shape => :polygon)
42
+ @arbiter.should_receive(:collide_circle_polygon?).with(a,b).and_return(true)
43
+
44
+ @arbiter.collide?(a,b).should be_true
45
+ end
46
+
47
+ it 'should call the correct polygon circle collision method' do
48
+ a = stub(:collidable_shape => :polygon)
49
+ b = stub(:collidable_shape => :circle)
50
+ @arbiter.should_receive(:collide_circle_polygon?).with(b,a).and_return(true)
51
+
52
+ @arbiter.collide?(a,b).should be_true
53
+ end
54
+ end
55
+
56
+ describe '#collide_circle_circle?' do
57
+ it 'should collide overlapping circles' do
58
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :circle)
59
+ b = stub(:center_x => 0, :center_y => 10, :radius => 3, :collidable_shape => :circle)
60
+ @arbiter.collide_circle_circle?(a, b).should be_true
61
+ end
62
+
63
+ it 'should collide a circle in a circle' do
64
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :circle)
65
+ b = stub(:center_x => 10, :center_y => 10, :radius => 30, :collidable_shape => :circle)
66
+ @arbiter.collide_circle_circle?(a, b).should be_true
67
+ end
68
+
69
+ it 'should not collide non-overlapping circles' do
70
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :circle)
71
+ b = stub(:center_x => 100, :center_y => 100, :radius => 30, :collidable_shape => :circle)
72
+ @arbiter.collide_circle_circle?(a, b).should be_false
73
+ end
74
+ end
75
+
76
+ describe '#collide_polygon_polygon?' do
77
+ it 'should not collide non-overlapping polys based on radius' do
78
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :polygon)
79
+ b = stub(:center_x => 61, :center_y => 0, :radius => 30, :collidable_shape => :polygon)
80
+ @arbiter.collide_polygon_polygon?(a,b).should be_false
81
+ end
82
+
83
+ it 'should not collide non-overlapping polys based on points' do
84
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :polygon,
85
+ :cw_world_points => [
86
+ [0,0],[0,30], [0,30]
87
+ ],
88
+ :cw_world_lines => [
89
+ [0,0],[0,30],
90
+ [0,30],[30,0],
91
+ [30,0],[0,0]
92
+ ],
93
+ :cw_world_edge_normals => [
94
+ [-30,0],
95
+ [30,30],
96
+ [0,-30]
97
+ ]
98
+
99
+ )
100
+ b = stub(:center_x => 60, :center_y => 0, :radius => 30, :collidable_shape => :polygon,
101
+ :cw_world_points => [
102
+ [60,0],[60,30], [90,0]
103
+ ],
104
+ :cw_world_lines => [
105
+ [60,0],[60,30],
106
+ [60,30],[90,0],
107
+ [90,0],[60,0]
108
+ ],
109
+ :cw_world_edge_normals => [
110
+ [-30,0],
111
+ [30,30],
112
+ [0,-30]
113
+ ]
114
+ )
115
+ @arbiter.collide_polygon_polygon?(a,b).should be_false
116
+ end
117
+
118
+ it 'should collide non-overlapping polys based on points' do
119
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :polygon,
120
+ :cw_world_points => [
121
+ [0,0],[0,30],[30,0]
122
+ ],
123
+ :cw_world_lines => [
124
+ [0,0],[0,30],
125
+ [0,30],[30,0],
126
+ [30,0],[0,0]
127
+ ],
128
+ :cw_world_edge_normals => [
129
+ [30,0],
130
+ [30,30],
131
+ [0,-30]
132
+ ]
133
+ )
134
+ b = stub(:center_x => 29, :center_y => 0, :radius => 30, :collidable_shape => :polygon,
135
+ :cw_world_points => [
136
+ [29,0],[29,30],[59,0]
137
+ ],
138
+ :cw_world_lines => [
139
+ [29,0],[29,30],
140
+ [29,30],[59,0],
141
+ [59,0],[29,0]
142
+ ],
143
+ :cw_world_edge_normals => [
144
+ [-30,0],
145
+ [30,30],
146
+ [0,-30]
147
+ ]
148
+ )
149
+ @arbiter.collide_polygon_polygon?(a,b).should be_true
150
+ end
151
+
152
+ it 'should collide completely overlapping polys based on points' do
153
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :polygon,
154
+ :cw_world_points => [
155
+ [0,0],[0,30],[30,0]
156
+ ],
157
+ :cw_world_lines => [
158
+ [0,0],[0,30],
159
+ [0,30],[30,0],
160
+ [30,0],[0,0]
161
+ ],
162
+ :cw_world_edge_normals => [
163
+ [30,0],
164
+ [30,30],
165
+ [0,-30]
166
+ ]
167
+ )
168
+ b = stub(:center_x => 2, :center_y => 0, :radius => 10, :collidable_shape => :polygon,
169
+ :cw_world_points => [[10,0],[10,20],[20,0]],
170
+ :cw_world_lines => [
171
+ [10,0],[10,20],
172
+ [10,20],[20,0],
173
+ [20,0],[10,0]
174
+ ],
175
+ :cw_world_edge_normals => [
176
+ [-20,0],
177
+ [-10,-20],
178
+ [0,-10]
179
+ ]
180
+ )
181
+ @arbiter.collide_polygon_polygon?(a,b).should be_true
182
+ end
183
+ end
184
+
185
+ describe '#collide_circle_polygon?' do
186
+ it 'should collide overlapping circle and polygon' do
187
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :circle)
188
+ b = stub(:center_x => 2, :center_y => 0, :radius => 10, :collidable_shape => :polygon,
189
+ :cw_world_points => [[10,0],[10,20],[20,0]],
190
+ :cw_world_lines => [
191
+ [10,0],[10,20],
192
+ [10,20],[20,0],
193
+ [20,0],[10,0]
194
+ ],
195
+ :cw_world_edge_normals => [
196
+ [-20,0],
197
+ [-10,-20],
198
+ [0,-10]
199
+ ]
200
+ )
201
+ @arbiter.collide_circle_polygon?(a, b).should be_true
202
+ end
203
+
204
+ it 'should not collide overlapping circle and polygon' do
205
+ a = stub(:center_x => 0, :center_y => 0, :radius => 30, :collidable_shape => :circle)
206
+ b = stub(:center_x => 200, :center_y => 0, :radius => 10, :collidable_shape => :polygon,
207
+ :cw_world_points => [[10,0],[10,20],[20,0]],
208
+ :cw_world_lines => [
209
+ [208,0],[208,20],
210
+ [208,20],[218,0],
211
+ [218,0],[208,0]
212
+ ],
213
+ :cw_world_edge_normals => [
214
+ [-20,0],
215
+ [-10,-20],
216
+ [0,-10]
217
+ ]
218
+ )
219
+ @arbiter.collide_circle_polygon?(a, b).should be_false
220
+ end
221
+ end
222
+
223
+ describe '#collide_aabb_aabb' do
224
+ it 'should collide overlapping boxes' do
225
+ a = stub(:center_x => 0, :center_y => 0, :width => 30, :height => 20,
226
+ :collidable_shape => :aabb, :radius => 10,
227
+ :cw_world_points => [
228
+ [-15,10],[15,10],
229
+ [15,-10], [-15,10]
230
+ ],
231
+ :cw_world_lines => [
232
+ [[-15,10],[15,10]],
233
+ [[15,10],[15,-10]],
234
+ [[15,-10],[-15,10]],
235
+ [[-15,10],[-15,10]]
236
+ ],
237
+ :cw_world_edge_normals => [[1,0],[0,1]])
238
+ b = stub(:center_x => 5, :center_y => 5, :width => 10, :height => 2,
239
+ :collidable_shape => :aabb, :radius => 10,
240
+ :cw_world_points => [
241
+ [0,6],[10,6],
242
+ [10,4], [0,6]
243
+ ],
244
+ :cw_world_lines => [
245
+ [[0,6],[10,6]],
246
+ [[10,6],[10,4]],
247
+ [[10,4],[0,6]],
248
+ [[0,6],[0,6]]
249
+ ],
250
+ :cw_world_edge_normals => [[1,0],[0,1]])
251
+
252
+ @arbiter.collide_aabb_aabb?(a,b).should be_true
253
+ end
254
+ end
255
+
256
+ describe '#collide_aabb_circle' do
257
+ it 'should collide overlapping box and circle'
258
+ end
259
+
260
+ describe "#find_collisions" do
261
+ it "runs callbacks w/ unique collisions"
262
+ end
263
+
264
+ end
@@ -2,10 +2,27 @@ require File.join(File.dirname(__FILE__),'helper')
2
2
  require 'behavior'
3
3
 
4
4
  describe 'A new behavior' do
5
+ before do
6
+ @actor = stub
7
+ @target = Behavior.new @actor
8
+ end
9
+
10
+ it 'should auto-require behaviors that it depends on'
11
+ it 'should relegate properly' do
12
+ @target.should_receive(:foo).and_return(:bar)
13
+ @target.relegates :foo
14
+
15
+ @actor.foo.should == :bar
16
+ end
5
17
 
6
- it 'should auto-require behaviors that it depends on' do
7
- actor = mock()
18
+ it 'should un-relegate properly' do
19
+ @target.should_receive(:foo).and_return(:bar)
20
+ @target.relegates :foo
21
+ @actor.foo.should == :bar
22
+
23
+ @target.removed
8
24
 
25
+ @actor.respond_to?(:foo).should be_false
9
26
  end
10
27
 
11
28
  end
@@ -4,12 +4,112 @@ require 'collidable'
4
4
  describe 'A new collidable behavior' do
5
5
  before do
6
6
  @stage = mock(:register_collidable => nil)
7
- opts = {:actor_type => :actor, :stage=>@stage, :input=>"input", :resources=> :rm}
8
- @actor = Actor.new opts
9
- @collidable = Collidable.new @actor
7
+ @actor_opts = {:actor_type => :actor, :stage=>@stage, :input=>"input", :resources=> :rm}
8
+ @actor = Actor.new @actor_opts
10
9
  end
11
10
 
12
- it 'should define methods on actor' do
13
- @actor.respond_to?(:shape).should be_true
11
+
12
+ describe "circle shape" do
13
+ before do
14
+ @behavior_opts = {:shape => :circle}
15
+ @collidable = Collidable.new @actor, @behavior_opts
16
+ end
17
+
18
+ it 'should recalculate_collidable_cache on update' do
19
+ @collidable.shape.should_receive(:recalculate_collidable_cache)
20
+ @collidable.update 4
21
+ end
22
+
23
+ it 'should relegate methods on actor' do
24
+ @collidable.should_receive(:width).and_return(44)
25
+ @actor.width.should == 44
26
+ @collidable.should_receive(:height).and_return(45)
27
+ @actor.height.should == 45
28
+
29
+ @collidable.should_receive(:collidable_shape).and_return(:circlez)
30
+ @actor.collidable_shape.should == :circlez
31
+ end
32
+
33
+ it 'should calculate center point for circle' do
34
+ @actor.x = 3
35
+ @actor.y = 6
36
+ @collidable = Collidable.new @actor, :shape => :circle, :radius => 20
37
+ @collidable.center_x.should be_close(23, 0.001)
38
+ @collidable.center_y.should be_close(26, 0.001)
39
+ end
14
40
  end
41
+
42
+ describe "polygon shape" do
43
+ it 'should calculate center point for polygon' do
44
+ @collidable = Collidable.new @actor, :shape => :polygon, :points => [[0,0],[10,7],[20,10]]
45
+ @collidable.center_x.should be_close(10, 0.001)
46
+ @collidable.center_y.should be_close(5, 0.001)
47
+ end
48
+
49
+ it 'should translate points to world coords for poly' do
50
+ @actor.x = 10
51
+ @actor.y = 5
52
+ @collidable = Collidable.new @actor, :shape => :polygon, :points => [[0,0],[10,7],[20,10]]
53
+ @collidable.cw_world_points.should == [[10,5],[20,12],[30,15]]
54
+ end
55
+
56
+ it 'should translate lines to world coords lines' do
57
+ @collidable = Collidable.new @actor, :shape => :polygon, :points => [[0,0],[10,7],[20,10]]
58
+
59
+ @collidable.cw_world_lines.should == [
60
+ [[0,0],[10,7]],
61
+ [[10,7],[20,10]],
62
+ [[20,10],[0,0]]
63
+ ]
64
+ end
65
+
66
+ it 'should translate world lines to edge normals' do
67
+ @collidable = Collidable.new @actor, :shape => :polygon,
68
+ :points => [[0,0],[10,7],[20,10]]
69
+
70
+ @collidable.cw_world_edge_normals.should == [
71
+ [-7,10], [-3,10], [10,-20]
72
+ ]
73
+ end
74
+
75
+ it 'should cache calcs until reset' do
76
+ @collidable = Collidable.new @actor, :shape => :polygon,
77
+ :points => [[0,0],[10,7],[20,10]]
78
+ # prime the cache
79
+ @collidable.cw_world_points.should == [[0,0],[10,7],[20,10]]
80
+ @collidable.cw_world_lines.should == [
81
+ [[0,0],[10,7]],
82
+ [[10,7],[20,10]],
83
+ [[20,10],[0,0]]
84
+ ]
85
+ @collidable.cw_world_edge_normals.should == [
86
+ [-7,10], [-3,10], [10,-20]
87
+ ]
88
+
89
+ @actor.x = 10
90
+ @actor.y = 5
91
+ @collidable.cw_world_points.should == [[0,0],[10,7],[20,10]]
92
+ @collidable.cw_world_lines.should == [
93
+ [[0,0],[10,7]],
94
+ [[10,7],[20,10]],
95
+ [[20,10],[0,0]]
96
+ ]
97
+ @collidable.cw_world_edge_normals.should == [
98
+ [-7,10], [-3,10], [10,-20]
99
+ ]
100
+
101
+ @collidable.clear_collidable_cache
102
+ @collidable.cw_world_points.should == [[10,5],[20,12],[30,15]]
103
+ @collidable.cw_world_lines.should == [
104
+ [[10,5],[20,12]],
105
+ [[20,12],[30,15]],
106
+ [[30,15],[10,5]]
107
+ ]
108
+ @collidable.cw_world_edge_normals.should == [
109
+ [-7,10], [-3,10], [10,-20]
110
+ ]
111
+
112
+ end
113
+ end
114
+
15
115
  end
@@ -2,7 +2,7 @@ here = File.dirname(__FILE__)
2
2
  gamebox_root = File.expand_path(File.join(here, '..', 'lib'))
3
3
 
4
4
  #$LOAD_PATH.unshift File.expand_path(gamebox_root, 'gamebox')
5
- require 'rubygems'
5
+ require File.expand_path(File.join(here, '..', 'load_paths'))
6
6
  require 'spec'
7
7
 
8
8
  # TODO this lives in both gamebox.rb and here... seems strange
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require File.join(File.dirname(__FILE__),'helper')
2
2
  require 'label'
3
3
 
4
4
  describe 'a new Label' do
@@ -3,7 +3,7 @@ require 'resource_manager'
3
3
 
4
4
  describe 'A new resource manager' do
5
5
  before do
6
- @res_man = ResourceManager.new
6
+ @res_man = ResourceManager.new :wrapped_screen => stub(:screen => :fake_gosu)
7
7
  end
8
8
 
9
9
  it 'should load an actor image' do
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require File.join(File.dirname(__FILE__),'helper')
2
2
  require 'spatial_hash'
3
3
 
4
4
  describe 'a new SpacialHash' do