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
@@ -2,45 +2,58 @@ require "enumerator"
2
2
 
3
3
  # SvgActor knows how to build himself based on an svg document based on the :name
4
4
  # passed in being the group name in the doc (layer).
5
- class SvgActor < Actor
6
-
7
- attr_accessor :segments, :type
8
- def setup
9
- @name = @opts[:name]
10
- @svg_doc = @opts[:svg_doc]
5
+ define_behavior :svg_built do
6
+
7
+ requires_behaviors :positioned
8
+ requires :physics_manager
9
+
10
+ setup do
11
+ name = @opts[:name]
12
+ svg_doc = @opts[:svg_doc]
11
13
 
12
- my_layer = @svg_doc.find_group_by_label(@name.to_s)
13
- build_from_vertices my_layer.path.vertices
14
+ my_layer = svg_doc.find_group_by_label(name.to_s)
15
+ segments = build_from_vertices my_layer.path.vertices
16
+
17
+ actor.has_attributes segments: segments,
18
+ name: name
14
19
  end
15
20
 
16
- def build_from_vertices(vertices)
17
-
18
- moment_of_inertia,mass = Float::INFINITY,Float::INFINITY
19
- terrain_body = CP::Body.new(mass,moment_of_inertia)
20
- elasticity = 0
21
- friction = 0.7
22
- thickness = 6
23
- @segments = []
24
- vertices.each_cons(2) do |a,b|
25
- seg = CP::Shape::Segment.new(terrain_body, a,b, thickness)
26
- seg.collision_type = @name
27
- seg.e = elasticity
28
- seg.u = friction
29
- seg.group = :terrain
30
- @segments << [a,b]
31
- @stage.space.add_static_shape(seg)
21
+ helpers do
22
+ def build_from_vertices(vertices)
23
+
24
+ moment_of_inertia,mass = Float::INFINITY,Float::INFINITY
25
+ terrain_body = CP::Body.new(mass,moment_of_inertia)
26
+ elasticity = 0
27
+ friction = 0.7
28
+ thickness = 6
29
+ segments = []
30
+ [].tap do |segments|
31
+ vertices.each_cons(2) do |a,b|
32
+ seg = CP::Shape::Segment.new(terrain_body, a,b, thickness)
33
+ seg.collision_type = @name
34
+ seg.e = elasticity
35
+ seg.u = friction
36
+ seg.group = :terrain
37
+ segments << [a,b]
38
+ physics_manager.space.add_static_shape(seg)
39
+ end
40
+ end
32
41
  end
33
42
  end
34
43
  end
35
44
 
36
- class SvgActorView < ActorView
37
- def draw(target, x_off, y_off, z)
38
- @actor.segments.each do |seg|
39
- p1 = seg[0]
40
- p2 = seg[1]
41
- # TODO pull in draw_line_s?
42
- target.draw_line p1.x+x_off, p1.y+y_off, p2.x+x_off, p2.y+y_off, [25,255,25,255], z
43
- #target.draw_line_s [p1.x+x_off,p1.y+y_off], [p2.x+x_off,p2.y+y_off], [25,255,25,255], 6
45
+ define_actor :svg_actor do
46
+ has_behavior :svg_built
47
+
48
+ view do
49
+ draw do |target, x_off, y_off, z|
50
+ actor.segments.each do |seg|
51
+ p1 = seg[0]
52
+ p2 = seg[1]
53
+ # TODO pull in draw_line_s?
54
+ target.draw_line p1.x+x_off, p1.y+y_off, p2.x+x_off, p2.y+y_off, [25,255,25,255], z
55
+ #target.draw_line_s [p1.x+x_off,p1.y+y_off], [p2.x+x_off,p2.y+y_off], [25,255,25,255], 6
56
+ end
44
57
  end
45
58
  end
46
59
  end
@@ -2,84 +2,64 @@
2
2
  # keeps track of an image for you based on the actor's class, and
3
3
  # current action, and frame num
4
4
  # by default it expects images to be:
5
- # data/graphics/classname/action/01..n.png
6
- class Animated < Behavior
7
- requires_behavior :updatable
8
-
9
- attr_accessor :frame_time, :frame_num, :animating, :frame_update_time
10
- def setup
5
+ # data/graphics/actor_type/action/01..n.png
6
+ Behavior.define :animated do
7
+ requires :resource_manager, :director
8
+ setup do
11
9
  @images = {}
12
10
  @frame_update_time = @opts[:frame_update_time]
13
11
  @frame_update_time ||= 60
14
12
  @frame_time = 0
15
-
13
+
16
14
  # all animated actors have to have an idle animation
17
15
  # data/graphics/ship/idle/1.png
18
16
  @frame_num = 0
19
- self.action = :idle
20
-
21
- relegates :image, :width, :height,
22
- :start_animating, :stop_animating, :animated,
23
- :action, :action=
24
-
25
- end
26
-
27
- def animated
28
- self
29
- end
30
17
 
31
- def width
32
- image.width
33
- end
18
+ actor.has_attributes action: :idle,
19
+ animating: true
20
+ actor.has_attributes :image, :width, :height
34
21
 
35
- def height
36
- image.height
37
- end
38
-
39
- def update(time)
40
- return unless @animating
41
- @frame_time += time
42
- if @frame_time > @frame_update_time
43
- next_frame
44
- @frame_time = @frame_time-@frame_update_time
22
+ actor.when :action_changed do |old_action, new_action|
23
+ action_changed old_action, new_action
24
+ actor.animating = @images[new_action].size > 1
45
25
  end
46
- end
47
26
 
48
- def next_frame()
49
- @frame_num = (@frame_num + 1) % @images[@action].size
50
- end
27
+ action_changed nil, actor.action
51
28
 
52
- # load all the images for this action
53
- def load_action(action)
54
- @actor.resource_manager.load_animation_set @actor, action
29
+ director.when :update do |time|
30
+ if actor.animating
31
+ @frame_time += time
32
+ if @frame_time > @frame_update_time
33
+ next_frame
34
+ @frame_time = @frame_time-@frame_update_time
35
+ end
36
+ set_image
37
+ end
38
+ end
55
39
  end
56
40
 
57
- def action
58
- @action
59
- end
41
+ helpers do
42
+ def next_frame
43
+ action_set = @images[actor.action]
44
+ @frame_num = (@frame_num + 1) % action_set.size unless action_set.nil?
45
+ end
60
46
 
61
- def action=(new_action)
62
- @images[new_action] ||= load_action(new_action)
63
- if @images[new_action].size > 1
64
- start_animating
65
- else
66
- stop_animating
47
+ def action_changed(old_action, new_action)
48
+ @images[new_action] ||= resource_manager.load_animation_set actor, new_action
49
+ @frame_num = 0
50
+ set_image
67
51
  end
68
- @frame_num = 0
69
- @action = new_action
70
- end
71
52
 
72
- # returns the current image, or nil if no action is defined
73
- def image
74
- @images[@action][@frame_num]
75
- end
53
+ def set_image
54
+ action_set = @images[actor.action]
55
+ raise "unknown action set #{actor.action} for #{actor}" if action_set.nil?
76
56
 
77
- def start_animating
78
- @animating = true
57
+ image = action_set[@frame_num]
58
+ actor.image = image
59
+ actor.width = image.width
60
+ actor.height = image.height
61
+ end
79
62
  end
80
63
 
81
- def stop_animating
82
- @animating = false
83
- end
84
64
 
85
65
  end
@@ -1,23 +1,23 @@
1
1
 
2
2
 
3
- class Audible < Behavior
3
+ Behavior.define :audible do
4
4
 
5
- def setup
6
- @sound_manager = @actor.stage.sound_manager
7
-
8
- audible_obj = self
9
- relegates :play_sound, :stop_sound
5
+ requires :sound_manager
6
+ setup do
7
+ reacts_with :play_sound, :stop_sound
10
8
  end
11
9
 
12
- # Plays a sound via the SoundManager. See SoundManager for
13
- # details on how to "define" sounds.
14
- def play_sound(*args)
15
- @sound_manager.play_sound *args
16
- end
10
+ helpers do
11
+ # Plays a sound via the SoundManager. See SoundManager for
12
+ # details on how to "define" sounds.
13
+ def play_sound(*args)
14
+ sound_manager.play_sound *args
15
+ end
17
16
 
18
- # Stops a sound via the SoundManager.
19
- def stop_sound(*args)
20
- @sound_manager.stop_sound *args
17
+ # Stops a sound via the SoundManager.
18
+ def stop_sound(*args)
19
+ sound_manager.stop_sound *args
20
+ end
21
21
  end
22
22
 
23
23
  end
@@ -1,53 +1,82 @@
1
+ # available shape_types are :circle, :polygon, :aabb
2
+ Behavior.define :collidable do
1
3
 
4
+ requires_behaviors :positioned
2
5
 
6
+ requires :stage
7
+ setup do
8
+ shape_type = opts[:shape]
3
9
 
10
+ w = actor.do_or_do_not(:width) || 1
11
+ h = actor.do_or_do_not(:height) || 1
12
+ hw = w / 2
13
+ hh = h / 2
14
+ x = (actor.do_or_do_not(:x) || 0) - hw
15
+ y = (actor.do_or_do_not(:y) || 0) - hh
4
16
 
17
+ actor.has_attributes( shape_type: shape_type,
18
+ width: w,
19
+ height: h,
20
+ x: x,
21
+ y: y )
5
22
 
6
- # available collidable_shapes are :circle, :polygon, :aabb
7
- class Collidable < Behavior
23
+ shape =
24
+ case shape_type
25
+ when :circle
26
+ CircleCollidable.new actor, opts
27
+ when :aabb
28
+ AaBbCollidable.new actor, opts
29
+ when :polygon
30
+ PolygonCollidable.new actor, opts
31
+ end
32
+ shape.setup
8
33
 
9
- attr_accessor :collidable_shape, :cw_local_points, :shape
34
+ actor.width = shape.width
35
+ actor.height = shape.height
36
+ bb = Rect.new
37
+ bb.x = actor.x
38
+ bb.y = actor.y
39
+ bb.w = actor.width
40
+ bb.h = actor.height
10
41
 
11
- def setup
12
- @shape = build_shape
13
42
 
14
- relegates :collidable_shape, :radius, :cw_world_points, :cw_world_lines, :center_x, :center_y, :cw_world_edge_normals
15
- relegates :width unless @actor.respond_to? :width
16
- relegates :height unless @actor.respond_to? :height
43
+ actor.has_attributes( shape: shape,
44
+ center_x: shape.center_x,
45
+ center_y: shape.center_y,
46
+ cw_world_points: shape.cw_world_points,
47
+ cw_world_lines: shape.cw_world_lines,
48
+ cw_world_edge_normals: shape.cw_world_edge_normals,
49
+ bb: bb,
50
+ radius: shape.radius
51
+ )
17
52
 
18
- register_actor
19
- end
53
+ stage.register_collidable actor
20
54
 
21
- def register_actor
22
- @actor.stage.register_collidable @actor
55
+ reacts_with :remove, :position_changed
23
56
  end
24
57
 
25
- def removed
26
- @actor.stage.unregister_collidable @actor
27
- super
28
- end
29
-
30
- def build_shape
31
- shape = nil
32
- @collidable_shape = opts[:shape]
33
- case @collidable_shape
34
- when :circle
35
- shape = CircleCollidable.new @actor, opts
36
- when :aabb
37
- shape = AaBbCollidable.new @actor, opts
38
- when :polygon
39
- shape = PolygonCollidable.new @actor, opts
58
+ helpers do
59
+ def remove
60
+ stage.unregister_collidable actor
40
61
  end
41
62
 
42
- shape.setup
43
- shape
44
- end
45
-
46
- def update(time)
47
- shape.update(time)
48
- end
63
+ def position_changed
64
+ shape = actor.shape
65
+ shape.recalculate_collidable_cache
66
+ actor.center_x = shape.center_x
67
+ actor.center_y = shape.center_y
68
+ actor.width = shape.width
69
+ actor.height = shape.height
70
+ actor.cw_world_points = shape.cw_world_points
71
+ actor.cw_world_lines = shape.cw_world_lines
72
+ actor.cw_world_edge_normals = shape.cw_world_edge_normals
73
+ actor.radius = shape.radius
49
74
 
50
- def method_missing(name, *args)
51
- @shape.send(name, *args)
75
+ bb = actor.bb
76
+ bb.x = actor.x
77
+ bb.y = actor.y
78
+ bb.w = actor.width
79
+ bb.h = actor.height
80
+ end
52
81
  end
53
82
  end
@@ -4,10 +4,10 @@ class AaBbCollidable < CollidableShape
4
4
  attr_accessor :cw_local_points
5
5
 
6
6
  def setup
7
- @collidable_shape = opts[:shape]
7
+ @shape_type = opts[:shape]
8
8
 
9
9
  @cw_local_points = opts[:cw_local_points]
10
- @cw_local_points ||= opts[:points]
10
+ @cw_local_points ||= opts[:points] || []
11
11
  @cw_world_points ||= build_aabb
12
12
 
13
13
  @radius = opts[:radius]
@@ -28,7 +28,6 @@ class AaBbCollidable < CollidableShape
28
28
  ]
29
29
  end
30
30
 
31
- # TODO infinite loop if actor hasn't defined width and it gets relegated to us
32
31
  def calculate_radius
33
32
  w = @actor.width
34
33
  hw = w * 0.5
@@ -1,5 +1,8 @@
1
1
  class CollidableShape
2
2
  attr_accessor :opts, :actor, :radius
3
+
4
+ attr_reader :cw_world_points, :cw_local_points, :cw_world_lines, :cw_world_edge_normals
5
+
3
6
  def initialize(actor, options)
4
7
  @opts = options
5
8
  @actor = actor
@@ -18,6 +21,7 @@ class CollidableShape
18
21
  @actor.y + @y_offset
19
22
  end
20
23
 
24
+ # TODO find out if this is called
21
25
  def setup
22
26
  end
23
27
 
@@ -26,10 +30,8 @@ class CollidableShape
26
30
  end
27
31
  alias :height :width
28
32
 
29
- def update(time)
30
- recalculate_collidable_cache
31
- end
32
-
33
33
  def recalculate_collidable_cache
34
34
  end
35
+
36
+
35
37
  end
@@ -4,7 +4,7 @@ class PolygonCollidable < CollidableShape
4
4
  attr_accessor :cw_local_points
5
5
 
6
6
  def setup
7
- @collidable_shape = opts[:shape]
7
+ @shape_type = opts[:shape]
8
8
 
9
9
  @cw_local_points = opts[:cw_local_points]
10
10
  @cw_local_points ||= opts[:points]
@@ -0,0 +1,48 @@
1
+ Behavior.define :emitting do
2
+ # options:
3
+ # delay: ms to wait between creating more particles
4
+ # particle_actor: actor to spawn as particle
5
+ # particle_opts: opts to be passed to the spawned particle
6
+ # ttl: ms to live (optional, will live forever if omitted)
7
+ # spawn_variance: dist in pixels to spawn away from emitter (default -10..10)
8
+ # location_tween: tween object that will be used to move the emitter (optional)
9
+ # follow: actor to follow (optional)
10
+ requires :stage
11
+ setup do
12
+ # TODO which opts do we want from actor and which from behavior?
13
+ opts = actor.opts
14
+ variance = opts[:spawn_variance] || (-10..10)
15
+
16
+ spawn_timer = "#{self.object_id}_spawn"
17
+ self.when :remove_me do
18
+ stage.remove_timer spawn_timer
19
+ end
20
+ stage.add_timer spawn_timer, opts[:delay] do
21
+ spawn_x = self.x + variance.sample
22
+ spawn_y = self.y + variance.sample
23
+
24
+ stage.spawn opts[:particle_actor], {x: spawn_x, y: spawn_y}.merge(opts[:particle_opts])
25
+ end
26
+ ttl = opts[:ttl]
27
+ if ttl
28
+ suicide_timer = "#{self.object_id}_ttl"
29
+ stage.add_timer suicide_timer, ttl do
30
+ stage.remove_timer suicide_timer
31
+ actor.remove
32
+ end
33
+ end
34
+
35
+ target = opts[:follow]
36
+ if target
37
+ self.x = target.x
38
+ self.y = target.y
39
+ target.when :x_changed do
40
+ self.x = target.x
41
+ end
42
+ target.when :y_changed do
43
+ self.y = target.y
44
+ end
45
+ end
46
+
47
+ end
48
+ end