gamebox 0.2.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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