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,56 @@
1
+
2
+ # ActorFactory is responsible for loading all Actors. It also creates the ActorView
3
+ # associated with the Actor and registers it to the Stage be drawn.
4
+ class ActorFactory
5
+ construct_with :input_manager, :wrapped_screen, :resource_manager,
6
+ :behavior_factory, :actor_view_factory, :this_object_context
7
+
8
+ # returns the newly created Actor after it and its ActorView has been created.
9
+ def build(actor, opts={})
10
+ merged_opts = opts.merge(actor_type: actor)
11
+
12
+ model = nil
13
+ this_object_context.in_subcontext do |actor_context|
14
+ begin
15
+ model = actor_context[:actor]
16
+
17
+ actor_definition = Actor.definitions[actor]
18
+ raise "#{actor} not found in Actor.definitions" if actor_definition.nil?
19
+ model.configure(merged_opts)
20
+
21
+ actor_definition.behaviors.each do |behavior|
22
+ beh_opts = {}
23
+ beh_key = behavior
24
+
25
+ if behavior.is_a?(Hash)
26
+ beh_opts = behavior.values.first
27
+ beh_key = behavior.keys.first
28
+ end
29
+
30
+ behavior_factory.add_behavior(model, beh_key, beh_opts)
31
+ end
32
+
33
+ actor_view_factory.build model, opts
34
+ rescue Exception => e
35
+ # binding.pry
36
+ raise """
37
+ #{actor} not found:
38
+ #{e.inspect}
39
+ #{e.backtrace[0..6].join("\n")}
40
+ """
41
+ end
42
+ end
43
+ model
44
+ end
45
+
46
+ def class_ancestors(actor)
47
+ klass = actor.class
48
+ [].tap { |actor_klasses|
49
+ while klass != Actor
50
+ actor_klasses << klass
51
+ klass = klass.superclass
52
+ end
53
+ }
54
+ end
55
+
56
+ end
@@ -0,0 +1,63 @@
1
+ class ActorView
2
+ construct_with :stage, :wrapped_screen, :resource_manager, :actor
3
+ public :stage, :wrapped_screen, :resource_manager, :actor
4
+
5
+ attr_accessor :layer, :parallax
6
+ def initialize
7
+ @layer = actor.do_or_do_not(:layer) || 0
8
+ @parallax = actor.do_or_do_not(:parallax) || 1
9
+
10
+ # TODO clean up the show/hide here make nice with visible behavior?
11
+ actor.when :remove_me do unregister end
12
+ actor.when :hide_me do unregister end
13
+ actor.when :show_me do register end
14
+
15
+ end
16
+
17
+ def register
18
+ stage.register_drawable self
19
+ end
20
+
21
+ def unregister
22
+ stage.unregister_drawable self
23
+ end
24
+
25
+ def screen_width
26
+ @screen_width ||= wrapped_screen.width
27
+ end
28
+
29
+ def screen_height
30
+ @screen_height ||= wrapped_screen.height
31
+ end
32
+
33
+ class << self
34
+ def define(actor_view_type, &blk)
35
+ @definitions ||= {}
36
+ definition = ActorViewDefinition.new
37
+ definition.instance_eval &blk if block_given?
38
+ @definitions[actor_view_type] = definition
39
+ end
40
+
41
+ def definitions
42
+ @definitions ||= {}
43
+ end
44
+ end
45
+
46
+ # TODO can these defs be unified?
47
+ class ActorViewDefinition
48
+ attr_accessor :draw_block, :configure_block, :required_injections
49
+ def requires(*injections_needed)
50
+ @required_injections = injections_needed
51
+ end
52
+
53
+ def configure(&configure_block)
54
+ @configure_block = configure_block
55
+ end
56
+
57
+ def draw(&draw_block)
58
+ @draw_block = draw_block
59
+ end
60
+ end
61
+
62
+
63
+ end
@@ -0,0 +1,40 @@
1
+
2
+ # ActorViewFactory is responsible for loading all ActorViews. It creates the ActorView
3
+ # associated with the Actor and registers it to the Stage be drawn.
4
+ class ActorViewFactory
5
+ construct_with :behavior_factory
6
+
7
+ # builds a new ActorView and configures it per its definition that is setup via ActorView.define
8
+ def build(actor, opts={})
9
+ # TODO have animated, graphical, physical set a view attr on actor
10
+ view_klass = opts[:view] || actor.do_or_do_not(:view) || "#{actor.actor_type}_view"
11
+ view_definition = ActorView.definitions[view_klass.to_sym]
12
+ view = nil
13
+ if view_definition
14
+ actor_context = actor.this_object_context
15
+ view = actor_context[:actor_view]
16
+ reqs = view_definition.required_injections
17
+ if reqs
18
+ reqs.each do |req|
19
+ object = actor_context[req]
20
+ view.define_singleton_method req do
21
+ components[req]
22
+ end
23
+ components = view.send :components
24
+ components[req] = object
25
+ end
26
+ end
27
+
28
+ view.define_singleton_method :draw, &view_definition.draw_block if view_definition.draw_block
29
+ if view_definition.configure_block
30
+ view.define_singleton_method :configure, &view_definition.configure_block
31
+ view.configure
32
+ end
33
+
34
+ behavior_factory.add_behavior(actor, :visible, view: view)
35
+ actor.react_to :show unless opts[:hide]
36
+ end
37
+ view
38
+ end
39
+
40
+ end
@@ -3,11 +3,11 @@ module Arbiter
3
3
  attr_reader :checks, :collisions
4
4
 
5
5
  def register_collidable(actor)
6
- stagehand(:spatial).add(actor)
6
+ stagehand(:spatial_tree).add(actor)
7
7
  end
8
8
 
9
9
  def unregister_collidable(actor)
10
- stagehand(:spatial).remove(actor)
10
+ stagehand(:spatial_tree).remove(actor)
11
11
  end
12
12
 
13
13
  def on_collision_of(first_objs, second_objs, &block)
@@ -52,35 +52,33 @@ module Arbiter
52
52
  end
53
53
  end
54
54
 
55
+ def interested_in_collision_of?(type1, type2)
56
+ @collision_handlers ||= {}
57
+ (@collision_handlers[type1] && @collision_handlers[type1][type2]) ||
58
+ (@collision_handlers[type2] && @collision_handlers[type2][type1])
59
+ end
60
+
55
61
  def find_collisions
56
- spatial_hash = stagehand(:spatial)
57
- collidable_actors = spatial_hash.moved_items
58
- @checks = 0
59
- @collisions = 0
62
+ aabb_tree = stagehand(:spatial_tree)
63
+ collidable_actors = aabb_tree.moved_items.values
64
+
60
65
  collisions = {}
61
66
 
62
67
  collidable_actors.each do |first|
63
- x = first.x - spatial_hash.cell_size
64
- y = first.y - spatial_hash.cell_size
65
- # TODO base this on size of object
66
- w = spatial_hash.cell_size * 3
67
- h = w
68
-
69
- tmp_collidable_actors = spatial_hash.neighbors_of(first)
70
-
71
- if first.is? :collidable
72
- tmp_collidable_actors.each do |second|
73
- @checks += 1
74
- if second.is? :collidable
75
- if first != second && collide?(first, second)
76
- collisions[second] ||= []
77
- if !collisions[second].include?(first)
78
- @collisions += 1
68
+ # if first.is? :collidable
69
+ # HUH? it appears that querying modifies the tree somehow?
70
+ aabb_tree.collisions(first) do |second|
71
+
72
+ # if second.is? :collidable
73
+ if first != second &&
74
+ interested_in_collision_of?(first.actor_type, second.actor_type) &&
75
+ collide?(first, second)
76
+ if !collisions[second] || (collisions[second] && !collisions[second].include?(first))
79
77
  collisions[first] ||= []
80
78
  collisions[first] << second
81
79
  end
82
- end
83
- end
80
+ # end
81
+ # end
84
82
  end
85
83
  end
86
84
  end
@@ -90,17 +88,16 @@ module Arbiter
90
88
  unique_collisions << [first,second]
91
89
  end
92
90
  end
93
-
94
91
  run_callbacks unique_collisions
92
+ aabb_tree.reset
95
93
  end
96
94
 
95
+
96
+
97
97
  def collide?(object, other)
98
- if !other.is? :collidable
99
- binding.pry
100
- end
101
- case object.collidable_shape
98
+ case object.shape_type
102
99
  when :circle
103
- case other.collidable_shape
100
+ case other.shape_type
104
101
  when :circle
105
102
  collide_circle_circle? object, other
106
103
  when :aabb
@@ -109,7 +106,7 @@ module Arbiter
109
106
  collide_circle_polygon? object, other
110
107
  end
111
108
  when :aabb
112
- case other.collidable_shape
109
+ case other.shape_type
113
110
  when :circle
114
111
  collide_aabb_circle? object, other
115
112
  when :aabb
@@ -118,7 +115,7 @@ module Arbiter
118
115
  collide_aabb_polygon? object, other
119
116
  end
120
117
  when :polygon
121
- case other.collidable_shape
118
+ case other.shape_type
122
119
  when :circle
123
120
  collide_polygon_circle? object, other
124
121
  when :aabb
@@ -159,8 +156,8 @@ module Arbiter
159
156
 
160
157
  # returns true if the projections overlap
161
158
  def project_and_detect(axis, a, b)
162
- a_min, a_max = send("#{a.collidable_shape}_interval", axis, a)
163
- b_min, b_max = send("#{b.collidable_shape}_interval", axis, b)
159
+ a_min, a_max = send("#{a.shape_type}_interval", axis, a)
160
+ b_min, b_max = send("#{b.shape_type}_interval", axis, b)
164
161
 
165
162
  a_min <= b_max && b_min <= a_max
166
163
  end
File without changes
@@ -0,0 +1,64 @@
1
+ # Behavior is any type of behavior an actor can exibit.
2
+ class Behavior
3
+ construct_with :actor
4
+
5
+ attr_accessor :opts
6
+
7
+ def configure(opts={})
8
+ @opts = opts
9
+ setup
10
+ end
11
+
12
+ def setup
13
+ end
14
+
15
+ def reacts_with(*messages_with_methods)
16
+ @message_handlers = messages_with_methods
17
+ end
18
+
19
+ def react_to(message_type, *opts)
20
+ # TODO perf analysis, should I use a hash here?
21
+ if @message_handlers && @message_handlers.include?(message_type)
22
+ send message_type, *opts
23
+ end
24
+ end
25
+
26
+ class << self
27
+
28
+ def define(behavior_type, &blk)
29
+ @definitions ||= {}
30
+ definition = BehaviorDefinition.new
31
+ definition.instance_eval &blk if block_given?
32
+ @definitions[behavior_type] = definition
33
+ end
34
+
35
+ def definitions
36
+ @definitions ||= {}
37
+ end
38
+ end
39
+
40
+ class BehaviorDefinition
41
+ attr_accessor :setup_block, :required_injections, :react_to_block, :required_behaviors,
42
+ :helpers_block
43
+
44
+ def requires(*injections_needed)
45
+ @required_injections = injections_needed
46
+ end
47
+
48
+ def requires_behaviors(*behaviors_needed)
49
+ @required_behaviors = behaviors_needed
50
+ end
51
+
52
+ def setup(&setup_block)
53
+ @setup_block = setup_block
54
+ end
55
+
56
+ def react_to(&react_to_block)
57
+ @react_to_block = react_to_block
58
+ end
59
+
60
+ def helpers(&helpers_block)
61
+ @helpers_block = helpers_block
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,56 @@
1
+ # BehaviorFactory is in charge of creating all behaviors and placing them in an Actor.
2
+ # Everything you want an Actor to _do_ is part of a Behavior. Actors are stupid buckets of data.
3
+ # Behaviors can be created by:
4
+ # has_behavior in an Actor's class definition
5
+ # or by dynamically creating one at runtime via another behavior.
6
+ class BehaviorFactory
7
+
8
+ # Build a behavior. Takes a symbol or a Hash.
9
+ # add_behavior(:shootable) or add_behavior(:shootable => {:range=>3})
10
+ # this will create a new instance of Shootable and pass
11
+ # :range=>3 to it
12
+ def add_behavior(actor, behavior_name, opts = {})
13
+ raise "nil actor" if actor.nil?
14
+ raise "nil behavior definition" if behavior_name.nil?
15
+
16
+ behavior_definition = Behavior.definitions[behavior_name]
17
+
18
+ raise "unknown behavior #{behavior_name}" unless behavior_definition
19
+ context = actor.this_object_context
20
+ context.in_subcontext do |behavioral_context|
21
+ behavioral_context[:behavior].tap do |behavior|
22
+ reqs = behavior_definition.required_injections
23
+ if reqs
24
+ reqs.each do |req|
25
+ object = context[req]
26
+ behavior.define_singleton_method req do
27
+ components[req]
28
+ end
29
+ components = behavior.send :components
30
+ components[req] = object
31
+ end
32
+ end
33
+
34
+ helpers = behavior_definition.helpers_block
35
+ if helpers
36
+ helpers_module = Module.new &helpers
37
+ behavior.extend helpers_module
38
+ end
39
+
40
+ behavior.define_singleton_method :react_to, behavior_definition.react_to_block if behavior_definition.react_to_block
41
+
42
+ deps = behavior_definition.required_behaviors
43
+ if deps
44
+ deps.each do |beh|
45
+ add_behavior actor, beh unless actor.has_behavior?(beh)
46
+ end
47
+ end
48
+ behavior.configure(opts)
49
+ behavior.instance_eval &behavior_definition.setup_block if behavior_definition.setup_block
50
+ actor.add_behavior behavior_name, behavior
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+ end
@@ -21,7 +21,7 @@ class ConfigManager
21
21
 
22
22
  # TODO make this path include that app name?
23
23
  def load_config(name)
24
- conf = YAML::load_file(CONFIG_PATH + name + ".yml")
24
+ conf = YAML::load_file("#{Gamebox.configuration.config_path}#{name}.yml")
25
25
  user_file = "#{ENV['HOME']}/.gamebox/#{name}.yml"
26
26
  if File.exist? user_file
27
27
  user_conf = YAML::load_file user_file
@@ -0,0 +1,39 @@
1
+ module Gamebox
2
+ # Pattern stolen from rspec for configuration
3
+ class Configuration
4
+ def self.add_setting(name, opts={})
5
+ if opts[:alias]
6
+ alias_method name, opts[:alias]
7
+ alias_method "#{name}=", "#{opts[:alias]}="
8
+ alias_method "#{name}?", "#{opts[:alias]}?"
9
+ else
10
+ define_method("#{name}=") {|val| settings[name] = val}
11
+ define_method(name) { settings.has_key?(name) ? settings[name] : opts[:default] }
12
+ define_method("#{name}?") { send name }
13
+ end
14
+ end
15
+
16
+ # add_setting :output, :alias => :output_stream
17
+ add_setting :config_path
18
+ add_setting :data_path
19
+ add_setting :music_path
20
+ add_setting :sound_path
21
+ add_setting :gfx_path
22
+ add_setting :fonts_path
23
+
24
+ add_setting :gb_config_path
25
+ add_setting :gb_data_path
26
+ add_setting :gb_music_path
27
+ add_setting :gb_sound_path
28
+ add_setting :gb_gfx_path
29
+ add_setting :gb_fonts_path
30
+
31
+ add_setting :game_name, default: "Untitled Game"
32
+
33
+ add_setting :stages, default: [:demo]
34
+
35
+ def settings
36
+ @settings ||= {}
37
+ end
38
+ end
39
+ end