gamebox 0.2.1 → 0.3.2

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 (95) hide show
  1. data/Gemfile +1 -8
  2. data/Rakefile +13 -37
  3. data/TODO.txt +27 -27
  4. data/docs/getting_started.rdoc +2 -2
  5. data/gamebox.gemspec +33 -191
  6. data/lib/gamebox.rb +18 -14
  7. data/lib/gamebox/actor.rb +37 -27
  8. data/lib/gamebox/actor_factory.rb +4 -5
  9. data/lib/gamebox/actor_view.rb +8 -0
  10. data/lib/gamebox/actors/collidable_debugger.rb +2 -2
  11. data/lib/gamebox/actors/curtain.rb +3 -3
  12. data/lib/gamebox/actors/emitter.rb +51 -0
  13. data/lib/gamebox/actors/label.rb +27 -7
  14. data/lib/gamebox/actors/logo.rb +1 -1
  15. data/lib/gamebox/actors/spatial_debugger.rb +25 -10
  16. data/lib/gamebox/arbiter.rb +61 -34
  17. data/lib/gamebox/behavior.rb +3 -3
  18. data/lib/gamebox/behaviors/animated.rb +1 -1
  19. data/lib/gamebox/behaviors/audible.rb +1 -1
  20. data/lib/gamebox/behaviors/collidable.rb +9 -4
  21. data/lib/gamebox/behaviors/collidable/aabb_collidable.rb +26 -1
  22. data/lib/gamebox/behaviors/collidable/circle_collidable.rb +3 -3
  23. data/lib/gamebox/behaviors/collidable/polygon_collidable.rb +1 -1
  24. data/lib/gamebox/behaviors/graphical.rb +30 -4
  25. data/lib/gamebox/behaviors/layered.rb +1 -1
  26. data/lib/gamebox/behaviors/physical.rb +113 -30
  27. data/lib/gamebox/behaviors/timed.rb +33 -0
  28. data/lib/gamebox/behaviors/updatable.rb +1 -1
  29. data/lib/gamebox/class_finder.rb +1 -21
  30. data/lib/gamebox/console_app.rb +33 -31
  31. data/lib/gamebox/constants.rb +481 -0
  32. data/lib/gamebox/data/config/objects.yml +7 -0
  33. data/lib/gamebox/gamebox_application.rb +10 -33
  34. data/lib/gamebox/gamebox_generator.rb +32 -32
  35. data/lib/gamebox/input_manager.rb +73 -32
  36. data/lib/gamebox/lib/inflector.rb +1 -1
  37. data/lib/gamebox/lib/range_ext.rb +5 -0
  38. data/lib/gamebox/lib/rect.rb +548 -548
  39. data/lib/gamebox/lib/sorted_list.rb +1 -1
  40. data/lib/gamebox/lib/symbol_ext.rb +8 -0
  41. data/lib/gamebox/physical_director.rb +1 -1
  42. data/lib/gamebox/physical_stage.rb +3 -3
  43. data/lib/gamebox/physics.rb +0 -3
  44. data/lib/gamebox/resource_manager.rb +22 -17
  45. data/lib/gamebox/sound_manager.rb +3 -2
  46. data/lib/gamebox/spatial_hash.rb +60 -31
  47. data/lib/gamebox/spatial_stagehand.rb +30 -6
  48. data/lib/gamebox/spec/helper.rb +7 -7
  49. data/lib/gamebox/stage.rb +18 -19
  50. data/lib/gamebox/stage_manager.rb +33 -23
  51. data/lib/gamebox/stagehand.rb +3 -0
  52. data/lib/gamebox/svg_document.rb +1 -1
  53. data/lib/gamebox/tasks/gamebox_tasks.rake +133 -0
  54. data/lib/gamebox/templates/actor.erb +0 -2
  55. data/lib/gamebox/templates/actor_view.erb +1 -3
  56. data/lib/gamebox/templates/template_app/Gemfile +3 -2
  57. data/lib/gamebox/templates/template_app/Rakefile +3 -8
  58. data/lib/gamebox/templates/template_app/config/environment.rb +7 -39
  59. data/lib/gamebox/templates/template_app/src/demo_stage.rb +1 -2
  60. data/lib/gamebox/templates/template_app/src/my_actor.rb +0 -3
  61. data/lib/gamebox/version.rb +2 -2
  62. data/lib/gamebox/viewport.rb +44 -8
  63. data/lib/gamebox/views/graphical_actor_view.rb +22 -16
  64. data/lib/gamebox/wrapped_screen.rb +9 -1
  65. data/script/perf_spatial_hash.rb +49 -58
  66. data/script/perf_struct_vs_array.rb +32 -0
  67. data/spec/actor_factory_spec.rb +61 -0
  68. data/spec/actor_spec.rb +24 -18
  69. data/spec/actor_view_spec.rb +51 -6
  70. data/spec/animated_spec.rb +27 -6
  71. data/spec/arbiter_spec.rb +12 -24
  72. data/spec/backstage_spec.rb +1 -1
  73. data/spec/behavior_spec.rb +3 -3
  74. data/spec/class_finder_spec.rb +13 -0
  75. data/spec/collidable_spec.rb +30 -10
  76. data/spec/emitter_spec.rb +20 -0
  77. data/spec/helper.rb +5 -21
  78. data/spec/input_manager_spec.rb +134 -0
  79. data/spec/label_spec.rb +0 -1
  80. data/spec/physical_spec.rb +114 -5
  81. data/spec/resource_manager_spec.rb +1 -2
  82. data/spec/spatial_hash_spec.rb +23 -7
  83. data/spec/spatial_stagehand_spec.rb +97 -0
  84. data/spec/stage_manager_spec.rb +0 -1
  85. data/spec/stage_spec.rb +2 -2
  86. data/spec/viewport_spec.rb +92 -48
  87. metadata +223 -119
  88. data/.gitignore +0 -11
  89. data/History.txt +0 -80
  90. data/VERSION +0 -1
  91. data/lib/gamebox/event_compat.rb +0 -285
  92. data/lib/gamebox/lib/diy.rb +0 -371
  93. data/lib/gamebox/lib/numbers_ext.rb +0 -3
  94. data/lib/gamebox/tasks/gamebox_tasks.rb +0 -61
  95. data/load_paths.rb +0 -20
@@ -1,43 +1,49 @@
1
- require 'actor_view'
1
+
2
2
 
3
3
  class GraphicalActorView < ActorView
4
4
  def draw(target, x_off, y_off, z)
5
- x = @actor.x
6
- y = @actor.y
5
+ x = actor.x
6
+ y = actor.y
7
7
 
8
8
  offset_x = x+x_off
9
9
  offset_y = y+y_off
10
10
 
11
- img = @actor.image
11
+ img = actor.image
12
12
  return if img.nil?
13
13
 
14
- #if @actor.is? :animated or
15
- if @actor.is? :physical
14
+ alpha = actor.respond_to?(:alpha) ? actor.alpha : 0xFF
15
+ color = Color.new(alpha,0xFF,0xFF,0xFF)
16
+
17
+ x_scale = actor.x_scale
18
+ y_scale = actor.y_scale
19
+
20
+ if actor.is? :physical
16
21
  img_w = img.width
17
22
  img_h = img.height
18
23
 
19
- offset_x = x-img_w/2 + x_off
20
- offset_y = y-img_h/2 + y_off
21
- img.draw_rot offset_x, offset_y, z, @actor.rotation
24
+ img.draw_rot offset_x, offset_y, z, actor.rotation, 0.5, 0.5, x_scale, y_scale
22
25
  else
23
- graphical_behavior = @actor.graphical if @actor.is? :graphical
26
+ graphical_behavior = actor.graphical if actor.is? :graphical
24
27
  if graphical_behavior && graphical_behavior.tiled?
25
28
  x_tiles = graphical_behavior.num_x_tiles
26
29
  y_tiles = graphical_behavior.num_y_tiles
27
- # img_w, img_h = *img.size
28
30
  img_w = img.width
29
31
  img_h = img.height
30
32
  x_tiles.times do |col|
31
33
  y_tiles.times do |row|
32
- # img.blit target.screen, [offset_x+col*img_w,offset_y+row*img_h]
33
- img.draw offset_x+col*img_w, offset_y+row*img_h, z
34
+ # TODO why is there a nasty black line between these that jitters?
35
+ img.draw_rot offset_x+col*img_w, offset_y+row*img_h, z, actor.rotation, x_scale, y_scale
34
36
  end
35
37
  end
36
38
  else
37
- # img.blit target.screen, [offset_x,offset_y]
38
- img.draw offset_x, offset_y, z
39
+ if actor.respond_to? :rotation
40
+ rot = actor.rotation || 0.0
41
+ img.draw_rot offset_x, offset_y, z, rot, 0.5, 0.5, x_scale, y_scale, color
42
+ else
43
+ img.draw offset_x, offset_y, z, x_scale, y_scale, color
44
+ end
39
45
  end
40
46
  end
41
- target.draw_line(offset_x,offset_y,offset_x+1,offset_y+1,[255,10,10],z)
42
47
  end
48
+
43
49
  end
@@ -12,6 +12,14 @@ class WrappedScreen
12
12
  @screen.send name, *args
13
13
  end
14
14
 
15
+ def width
16
+ @screen.fullscreen? ? screen_width : @screen.width
17
+ end
18
+
19
+ def height
20
+ @screen.fullscreen? ? screen_height : @screen.height
21
+ end
22
+
15
23
  def draw_box(x1,y1,x2,y2,color, z)
16
24
  c = convert_color(color)
17
25
  @screen.draw_line x1, y1, c, x2, y1, c, z
@@ -28,7 +36,7 @@ class WrappedScreen
28
36
  CIRCLE_STEP = 10
29
37
  # is very expensive
30
38
  # cache it if you can somehow
31
- def draw_circle(cx,cy,r,color, z)
39
+ def draw_circle(cx,cy,r,color, z, step=CIRCLE_STEP)
32
40
  c_color = convert_color(color)
33
41
 
34
42
  x1, y1 = 0, -r
@@ -1,73 +1,64 @@
1
- $: << File.dirname(__FILE__)+"/../lib/gamebox"
1
+ require 'bundler'
2
+ Bundler.setup
2
3
 
3
- require 'spatial_hash'
4
- require 'new_spatial_hash'
4
+ require 'constructor'
5
+ require 'publisher'
6
+ require 'gamebox'
5
7
  require 'benchmark'
6
8
 
7
- Shape = Struct.new(:x,:y,:width,:height)
9
+ class Arb
10
+ include Arbiter
11
+ extend Publisher
12
+ can_fire_anything
8
13
 
9
- def do_it(hash, num_times, obj_size)
10
- num_times.times do |i|
11
- hash.add(Shape.new(i,i,obj_size,obj_size))
14
+ def initialize(spatial)
15
+ @spatial = spatial
16
+ on_collision_of :otherthingy, :thingy do |f,b|
17
+ puts "collide"
18
+ end
12
19
  end
13
-
14
- num_times.times do |i|
15
- hash.items_at i, i
20
+ def stagehand(name)
21
+ @spatial
16
22
  end
17
23
 
18
- hash.rehash
19
- hash.rehash
20
- hash.rehash
21
- hash.rehash
24
+ end
22
25
 
23
- num_times.times do |i|
24
- hash.items_at i, i
26
+ class Shape
27
+ extend Publisher
28
+ can_fire_anything
29
+ attr_accessor :x,:y,:width,:height,:collidable_shape,:radius
30
+ def initialize(*args)
31
+ @x,@y,@width,@height,@collidable_shape,@radius = *args
25
32
  end
33
+
34
+ def center_x;self.x;end
35
+ def center_y;self.y;end
36
+ def actor_type;:thingy;end
26
37
  end
27
38
 
28
- OldSpatialHash = SpatialHash
29
-
30
- Benchmark.bm(60) do|b|
31
-
32
- @lots = 1_000
33
- @small_grid = 5
34
- @medium_grid = 80
35
-
36
- @small_object = 2
37
- @medium_object = 20
38
- @large_object = 100
39
-
40
- impls = %w{old new}
41
- impls.each do |impl|
42
- klass = ObjectSpace.const_get "#{impl.capitalize}SpatialHash"
43
- b.report("#{impl} w/ lots of small objects in small size grid") do
44
- hash = klass.new @small_grid, true
45
- do_it(hash,@lots, @small_object)
46
- end
47
-
48
- b.report("#{impl} w/ lots of medium objects in small size grid") do
49
- hash = klass.new @small_grid, true
50
- do_it(hash,@lots, @medium_object)
51
- end
52
-
53
- b.report("#{impl} w/ lots of small objects in medium size grid") do
54
- hash = klass.new @medium_grid, true
55
- do_it(hash,@lots, @small_object)
56
- end
39
+ actor_count = 100
40
+ loop_count = 100
41
+ obj_size = 40
42
+ cell_size = 80
57
43
 
58
- b.report("#{impl} w/ lots of medium objects in medium size grid") do
59
- hash = klass.new @medium_grid, true
60
- do_it(hash,@lots, @medium_object)
61
- end
44
+ hash = SpatialHash.new cell_size#, true
45
+ arb = Arb.new hash
46
+ actor_count.times do |i|
47
+ shape = Shape.new(i*20, i*20, obj_size,obj_size,:circle,obj_size)
48
+ arb.register_collidable shape
49
+ end
62
50
 
63
- b.report("#{impl} w/ lots of large objects in small size grid") do
64
- hash = klass.new @small_grid, true
65
- do_it(hash,@lots, @large_object)
66
- end
67
- b.report("#{impl} w/ lots of large objects in small size grid no resize") do
68
- hash = klass.new @small_grid, false
69
- do_it(hash,@lots, @large_object)
51
+ Benchmark.bm(60) do|b|
52
+ #30.times do |i|
53
+ hash_cell_size = cell_size #+ 5*i
54
+ hash.cell_size = hash_cell_size
55
+ b.report("#{actor_count} actors w/ size #{obj_size} cell size #{hash_cell_size} for #{loop_count} update loops") do
56
+ loop_count.times do
57
+ hash.rehash
58
+ arb.find_collisions
70
59
  end
71
- end
60
+ end
61
+ end
62
+ #end
72
63
 
73
- end
64
+ puts "hash auto-size:#{hash.cell_size}"
@@ -0,0 +1,32 @@
1
+ require 'benchmark'
2
+
3
+ # Point = Struct.new :x, :y
4
+ class Point
5
+ attr_accessor :x, :y
6
+ def initialize(x,y)
7
+ @x = x
8
+ @y = y
9
+ end
10
+ end
11
+ NUM = 10_000_000
12
+ Benchmark.bm(60) do |b|
13
+ b.report("array") do
14
+ NUM.times do
15
+ it = [4,6]
16
+ it[0] = 1
17
+ it[1] = 3
18
+ it[0]
19
+ it[1]
20
+ end
21
+ end
22
+ b.report("struct") do
23
+ NUM.times do
24
+ it = Point.new 4, 6
25
+ it.x = 1
26
+ it.y = 3
27
+ it.x
28
+ it.y
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,61 @@
1
+ require File.join(File.dirname(__FILE__),'helper')
2
+ describe ActorFactory do
3
+ before do
4
+ @input_manager = mock
5
+ @screen = mock
6
+ @stage = mock
7
+ @resource_manager = mock
8
+ @stage = mock
9
+ @stage.stubs(:resource_manager).returns(@resource_manager)
10
+ @director = mock
11
+ params = {:input_manager => @input_manager, :wrapped_screen => @screen}
12
+ @target = ActorFactory.new params
13
+ @target.director = @director
14
+ @opts = Actor::DEFAULT_PARAMS.merge({:foo => :bar})
15
+ @basic_opts = {
16
+ :stage => @stage,
17
+ :input => @input_manager,
18
+ :director => @director,
19
+ :resources => @resource_manager,
20
+ :wrapped_screen => @screen,
21
+ }
22
+ @merged_opts = @basic_opts.merge(@opts)
23
+
24
+ end
25
+
26
+ describe "#build" do
27
+ it "creates an Actor instance and registers the view" do
28
+
29
+ view_actor = nil
30
+ @stage.expects(:register_drawable).with() do |view|
31
+ view.class.should == ActorView
32
+ view.stage.should == @stage
33
+ view.wrapped_screen.should == @screen
34
+ view.actor.class.should == Actor
35
+ view_actor = view.actor
36
+ end
37
+ @merged_opts[:actor_type] = :actor
38
+
39
+ act = @target.build :actor, @stage, @opts
40
+ act.opts.should == @merged_opts
41
+ act.class.should == Actor
42
+ act.should == view_actor
43
+ end
44
+
45
+ it "creates an Actor instance with no view" do
46
+ @merged_opts[:actor_type] = :no_view_actor
47
+
48
+ act = @target.build :no_view_actor, @stage, @opts
49
+ act.opts.should == @merged_opts
50
+ act.class.should == NoViewActor
51
+ end
52
+
53
+ it "nil on actor not found" do
54
+ lambda{ @target.build :no_actor, @stage, @opts }.should raise_error("no_actor not found")
55
+ end
56
+
57
+ end
58
+
59
+ class NoViewActor < Actor
60
+ end
61
+ end
data/spec/actor_spec.rb CHANGED
@@ -1,42 +1,40 @@
1
1
  require File.join(File.dirname(__FILE__),'helper')
2
- require 'actor'
3
- require 'behavior'
4
-
5
2
  describe 'A new actor' do
6
- before do
7
- opts = {:stage=>"stage", :input=>"input",
3
+ let(:stage) { mock }
4
+ subject {
5
+ opts = {:stage=>stage, :input=>"input",
8
6
  :resources=>"resource", :actor_type => :actor}
9
- @actor = Actor.new opts
10
- end
7
+ Actor.new opts
8
+ }
11
9
 
12
10
  it 'should be alive' do
13
- @actor.alive?.should be_true
11
+ subject.alive?.should be_true
14
12
  end
15
13
 
16
14
  it 'should be the correct type' do
17
- @actor.actor_type.should == :actor
15
+ subject.actor_type.should == :actor
18
16
  end
19
17
 
20
18
  it 'should be at (0,0)' do
21
- @actor.x.should equal(0)
22
- @actor.y.should equal(0)
19
+ subject.x.should equal(0)
20
+ subject.y.should equal(0)
23
21
  end
24
22
 
25
23
  it 'should have access to backstage' do
26
- @actor.stage = mock(:backstage => :stuff)
27
- @actor.backstage.should == :stuff
24
+ subject.stage = mock(:backstage => :stuff)
25
+ subject.backstage.should == :stuff
28
26
  end
29
27
 
30
28
  it 'should have atts set' do
31
- @actor.stage.should == "stage"
32
- @actor.input_manager.should == "input"
33
- @actor.resource_manager.should == "resource"
34
- @actor.behaviors.size.should equal(0)
29
+ subject.stage.should == stage
30
+ subject.input_manager.should == "input"
31
+ subject.resource_manager.should == "resource"
32
+ subject.behaviors.size.should equal(0)
35
33
  end
36
34
 
37
35
  it 'should fire anything' do
38
36
  Proc.new {
39
- @actor.when :foofoo_bar do
37
+ subject.when :foofoo_bar do
40
38
  "blah"
41
39
  end
42
40
  }.should_not raise_error
@@ -52,6 +50,14 @@ describe 'A new actor' do
52
50
  @james.is?(:smart).should be_true
53
51
  @james.instance_variable_get('@behaviors')[:smart].instance_variable_get('@opts').should == {:really=>true}
54
52
  end
53
+
54
+ describe '#viewport' do
55
+ it 'should return the stages viewport' do
56
+ stage.stubs(:viewport).returns(:da_viewport)
57
+ subject.viewport.should == :da_viewport
58
+ end
59
+ end
60
+
55
61
  end
56
62
 
57
63
  class Cool < Behavior; end
@@ -1,16 +1,61 @@
1
1
  require File.join(File.dirname(__FILE__),'helper')
2
- require 'actor_view'
2
+
3
3
 
4
4
  describe 'A new actor view' do
5
+ before do
6
+ @actor = mock
7
+ @stage = mock
8
+ @actor.stubs :when
9
+ end
5
10
 
6
11
  it 'should be layered 0/1 by default' do
7
- @test_me = ActorView.new :stage, Actor.new({}), :wrapped_screen
12
+ @actor.expects(:is?).with(:layered).returns(false)
13
+ @test_me = ActorView.new @stage, @actor, :wrapped_screen
8
14
  @test_me.layer.should == 0
9
15
  @test_me.parallax.should == 1
10
16
  end
11
17
 
12
- it 'should call setup on creation; tests that require subclassing seem wrong...'
13
- it 'should accept layered behavior params from actor'
14
- it 'should register for show/hide/remove events'
15
- it 'should manage a cached surface for drawing'
18
+ it 'should call setup on creation' do
19
+ ActorView.any_instance.expects :setup
20
+ @actor.expects(:is?).with(:layered).returns(false)
21
+ @test_me = ActorView.new @stage, @actor, :wrapped_screen
22
+ end
23
+
24
+ it 'should accept layered behavior params from actor' do
25
+ @actor.stubs(:layer => 6, :parallax => 3)
26
+ @actor.expects(:is?).with(:layered).returns(true)
27
+ @test_me = ActorView.new @stage, @actor, :wrapped_screen
28
+
29
+ @test_me.layer.should == 6
30
+ @test_me.parallax.should == 3
31
+ end
32
+
33
+ it 'should register for show events' do
34
+ @actor = Actor.new({})
35
+
36
+ @test_me = ActorView.new @stage, @actor, :wrapped_screen
37
+ @stage.expects(:register_drawable).with(@test_me)
38
+
39
+ @actor.send :fire, :show_me
40
+ end
41
+
42
+ it 'should register for hide events' do
43
+ @actor = Actor.new({})
44
+
45
+ @test_me = ActorView.new @stage, @actor, :wrapped_screen
46
+ @stage.expects(:unregister_drawable).with(@test_me)
47
+
48
+ @actor.send :fire, :hide_me
49
+ end
50
+
51
+ it 'should register for remove events' do
52
+ @actor = Actor.new({})
53
+
54
+ @test_me = ActorView.new @stage, @actor, :wrapped_screen
55
+ @stage.expects(:unregister_drawable).with(@test_me)
56
+
57
+ @actor.send :fire, :remove_me
58
+ end
59
+
60
+ it 'should manage a cached surface for drawing (possibly use record{})'
16
61
  end