gamebox 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -30,8 +30,8 @@ The reason I wrote Gamebox is twofold: first, to aid in 48 hour game writing com
30
30
 
31
31
  To create a new Gamebox project run:
32
32
 
33
- ```bash
34
- gamebox zapper
33
+ ```
34
+ $ gamebox new zapper
35
35
  ```
36
36
 
37
37
  This will create the directory structure and needed files to get a basic actor up on the screen:
@@ -61,10 +61,10 @@ zapper
61
61
 
62
62
  To run your game:
63
63
 
64
- ```bash
65
- cd zapper
66
- bundle
67
- rake
64
+ ```
65
+ $ cd zapper
66
+ $ bundle
67
+ $ rake
68
68
  ```
69
69
 
70
70
  ## Stages
@@ -26,7 +26,7 @@ end
26
26
 
27
27
  require "#{GAMEBOX_PATH}/version.rb"
28
28
  require 'require_all'
29
- directory_load_order = %w(lib core post_setup_handlers actors behaviors views stagehands)
29
+ directory_load_order = %w(lib core post_setup_handlers actors behaviors views)
30
30
  directory_load_order.each do |dir|
31
31
  require_all "#{GAMEBOX_PATH}/#{dir}/**/*.rb"
32
32
  end
@@ -1,4 +1,4 @@
1
- Behavior.define :fps_label_updater do
1
+ define_behavior :fps_label_updater do
2
2
  requires :director, :stage
3
3
  setup do
4
4
  @label = stage.create_actor :label, actor.attributes
@@ -6,10 +6,12 @@ Behavior.define :fps_label_updater do
6
6
  @label.text = Gosu.fps
7
7
  end
8
8
  end
9
- react_to do |msg, *args|
10
- @label.remove if msg == :remove
9
+
10
+ remove do
11
+ @label.remove
11
12
  end
12
13
  end
13
- Actor.define :fps do
14
+
15
+ define_actor :fps do
14
16
  has_behavior :fps_label_updater
15
17
  end
@@ -20,18 +20,34 @@ class Actor
20
20
  has_attributes opts
21
21
  end
22
22
 
23
- # Used by BehaviorFactory#add_behavior.
24
- # That's probably what you want to use from within another behavior
23
+ # Adds the behavior object to the Actor. You should never use
24
+ # this method in your game.
25
25
  def add_behavior(name, behavior)
26
26
  @behaviors[name] = behavior
27
27
  end
28
28
 
29
+ # Removes the behavior object from the Actor.
30
+ # Sends :remove reaction to the removed behavior.
31
+ # You should never use this method in your game.
29
32
  def remove_behavior(name)
30
33
  @behaviors.delete(name).tap do |behavior|
31
34
  behavior.react_to :remove if behavior
32
35
  end
33
36
  end
34
37
 
38
+ # Returns true if the Actor has the named behavior.
39
+ #
40
+ # This is mostly used internally by Gamebox. You should favor
41
+ # not knowing behaviors if possible and instead look at the
42
+ # Actor's attributes via #do_or_do_not
43
+ def has_behavior?(name)
44
+ @behaviors[name]
45
+ end
46
+
47
+ # Propogates the reaction to all behaviors of the Actor.
48
+ # Any behavior can react to these messages.
49
+ #
50
+ # @see Behavior#reacts_with
35
51
  def react_to(message, *opts, &blk)
36
52
  # TODO cache the values array?
37
53
  @behaviors.values.each do |behavior|
@@ -40,20 +56,18 @@ class Actor
40
56
  nil
41
57
  end
42
58
 
43
- def has_behavior?(name)
44
- @behaviors[name]
45
- end
46
-
47
59
  def emit(event, *args)
48
60
  fire event, *args
49
61
  end
50
62
 
51
- # Tells the actor's Director that he wants to be removed; and unsubscribes
52
- # the actor from all input events.
63
+ # Sets the Actor to no longer being alive.
64
+ #
65
+ # Sends a :remove reaction to all the Actor's behaviors.
66
+ # Emits a :remove_me event.
53
67
  def remove
54
68
  self.alive = false
55
69
  react_to :remove
56
- fire :remove_me
70
+ emit :remove_me
57
71
  end
58
72
 
59
73
  def input
@@ -5,6 +5,18 @@ class ActorDefinition
5
5
  @attributes = []
6
6
  end
7
7
 
8
+ # Setup default behaviors for this Actor
9
+ #
10
+ # # takes a block with method missing magic
11
+ # has_behaviors do
12
+ # shooter range: 12
13
+ # end
14
+ #
15
+ # # takes a list of optionless behaviors
16
+ # has_behaviors :jumper, :shielded
17
+ #
18
+ # # takes a hash of behavior name to options
19
+ # has_behaviors shooter: {range: 12}
8
20
  def has_behaviors(*behaviors, &blk)
9
21
  if block_given?
10
22
  collector = MethodMissingCollector.new
@@ -23,6 +35,13 @@ class ActorDefinition
23
35
  end
24
36
  alias has_behavior has_behaviors
25
37
 
38
+ # Setup observable attributes for the Actor and optionally default values
39
+ #
40
+ # # takes list of attributes (values will be nil)
41
+ # has_attributes :x, :y
42
+ #
43
+ # # takes hash of attributes with values
44
+ # has_attributes x: 5, y: 12
26
45
  def has_attributes(*attributes)
27
46
  attributes.each do |att|
28
47
  @attributes << att
@@ -30,10 +49,23 @@ class ActorDefinition
30
49
  end
31
50
  alias has_attribute has_attributes
32
51
 
52
+ # Defines an ActorView for this Actor with the correct name.
53
+ #
54
+ # Exactly the same as calling define_actor_view with :my_actor_view.
55
+ #
56
+ # Do not call more than once.
57
+ #
58
+ # @see GameboxDSL#define_actor_view
33
59
  def view(&blk)
34
60
  @view_blk = blk
35
61
  end
36
62
 
63
+ # Defines a Behavior with the Actor type as the name and adds it to the Actor.
64
+ #
65
+ # Exactly the same as calling define_behavior with :my_actor, and adding the
66
+ # behavior to the Actor.
67
+ #
68
+ # Do not call more than once.
37
69
  def behavior(&blk)
38
70
  @behavior_blk = blk
39
71
  end
@@ -1,17 +1,45 @@
1
1
  class ActorViewDefinition
2
2
  attr_accessor :draw_block, :setup_block, :required_injections, :helpers_block, :source
3
+
4
+ # Sets the dependencies for this ActorView.
5
+ #
6
+ # These will be pulled from the Actor's object context at view construction time.
7
+ #
8
+ # requires :resource_manager
9
+ #
3
10
  def requires(*injections_needed)
4
11
  @required_injections = injections_needed
5
12
  end
6
13
 
14
+ # Setup callback that is called when the view is constructed. The actor will
15
+ # be set before your setup block is executed.
16
+ #
17
+ # setup do
18
+ # resource_manager.load_image('something.png')
19
+ # end
20
+ #
7
21
  def setup(&setup_block)
8
22
  @setup_block = setup_block
9
23
  end
10
24
 
25
+ # Draw callback that is called when the view needs to draw.
26
+ #
27
+ # draw do |screen, x_offset, y_offset, z|
28
+ # ...
29
+ # end
30
+ #
11
31
  def draw(&draw_block)
12
32
  @draw_block = draw_block
13
33
  end
14
34
 
35
+ # Define methods and include modules for use by your view.
36
+ # helpers do
37
+ # include MyHelper
38
+ # def do_some_view_calc
39
+ # ...
40
+ # end
41
+ # end
42
+ #
15
43
  def helpers(&helper_block)
16
44
  @helpers_block = helper_block
17
45
  end
@@ -3,11 +3,15 @@ module Arbiter
3
3
  attr_reader :checks, :collisions
4
4
 
5
5
  def register_collidable(actor)
6
- stagehand(:spatial_tree).add(actor)
6
+ aabb_tree.add(actor)
7
7
  end
8
8
 
9
9
  def unregister_collidable(actor)
10
- stagehand(:spatial_tree).remove(actor)
10
+ aabb_tree.remove(actor)
11
+ end
12
+
13
+ def aabb_tree
14
+ @aabb_tree ||= SpatialTree.new(self)
11
15
  end
12
16
 
13
17
  def on_collision_of(first_objs, second_objs, &block)
@@ -59,7 +63,6 @@ module Arbiter
59
63
  end
60
64
 
61
65
  def find_collisions
62
- aabb_tree = stagehand(:spatial_tree)
63
66
  collidable_actors = aabb_tree.moved_items.values
64
67
 
65
68
  collisions = {}
@@ -4,30 +4,48 @@ class Behavior
4
4
 
5
5
  attr_accessor :opts
6
6
 
7
- def configure(opts={})
8
- @opts = opts
9
- setup
10
- end
11
-
12
- def setup
13
- end
14
-
7
+ # Specifies messages that your behavior is interested in and
8
+ # that you have defined methods for in your helpers block.
9
+ #
10
+ # reacts_with :remove
11
+ #
12
+ # helpers do
13
+ # def remove
14
+ # input_manager.unsubscribe_all self
15
+ # end
16
+ # end
15
17
  def reacts_with(*messages_with_methods)
16
- # TODO do a merge here..
17
- @message_handlers = messages_with_methods
18
+ @message_handlers ||= Set.new
19
+ @message_handlers.merge(messages_with_methods)
18
20
  end
19
21
 
22
+ # Dispatches reactions to helper methods based on name.
23
+ # See BehaviorDefinition to see how to override this.
24
+ #
25
+ # @see BehaviorDefinition
26
+ # @see Actor#react_to
20
27
  def react_to(message_type, *opts, &blk)
21
- # TODO perf analysis, should I use a hash here?
22
28
  if @message_handlers && @message_handlers.include?(message_type)
23
29
  send message_type, *opts, &blk
24
30
  end
25
31
  end
26
32
 
33
+ # Builds and adds a behavior based on the name and options passed in.
34
+ #
35
+ # actor.input.when :shields_up do
36
+ # add_behavior :invincible, duration: actor.shield_charge
37
+ # end
38
+ #
27
39
  def add_behavior(behavior_name, opts = {})
28
40
  behavior_factory.add_behavior actor, behavior_name, opts
29
41
  end
30
42
 
43
+ # Removes the behavior by name. Any added attributes will remain on the actor.
44
+ #
45
+ # actor.input.when :shields_down do
46
+ # remove_behavior :invincible
47
+ # end
48
+ #
31
49
  def remove_behavior(behavior_name)
32
50
  actor.remove_behavior(behavior_name)
33
51
  end
@@ -1,23 +1,73 @@
1
1
  class BehaviorDefinition
2
- attr_accessor :setup_block, :required_injections, :react_to_block, :required_behaviors,
2
+ attr_accessor :setup_block, :remove_block, :required_injections, :react_to_block, :required_behaviors,
3
3
  :helpers_block, :source
4
4
 
5
+ # Sets the dependencies for this Behavior.
6
+ #
7
+ # These will be pulled from the Actor's object context at view construction time.
8
+ #
9
+ # requires :input_manager, :timer_manager, :director
10
+ #
5
11
  def requires(*injections_needed)
6
12
  @required_injections = injections_needed
7
13
  end
8
14
 
15
+ # Sets the behavior dependencies for this Behavior.
16
+ #
17
+ # Any behaviors listed here that are not on the actor will be constructed and added without any opts.
18
+ #
19
+ # requires_behaviors :positioned
20
+ #
9
21
  def requires_behaviors(*behaviors_needed)
10
22
  @required_behaviors = behaviors_needed
11
23
  end
12
24
 
25
+ # Setup callback that is called when the behavior is added. The actor will
26
+ # be set before your setup block is executed, and the opts method will be available.
27
+ #
28
+ # setup do
29
+ # actor.has_attributes speed: opts[:speed]
30
+ # input_manager.when :down, KbSpace do
31
+ # jump
32
+ # end
33
+ # end
34
+ #
13
35
  def setup(&setup_block)
14
36
  @setup_block = setup_block
15
37
  end
16
38
 
39
+ # Remove callback that is called when the behavior is removed. The actor will
40
+ # still be available.
41
+ #
42
+ # remove do
43
+ # input_manager.unsubscribe_all self
44
+ # end
45
+ #
46
+ def remove(&remove_block)
47
+ @remove_block = remove_block
48
+ end
49
+
50
+ # Override the default react_to method of the behavior. You should probably not be doing this and should be calling #reacts_with in #setup.
51
+ #
52
+ # react_to do |message_type, *opts, &blk|
53
+ # case message_type
54
+ # when :blow_up
55
+ # ..
56
+ # end
57
+ #
58
+ # @see Behavior#reacts_with
17
59
  def react_to(&react_to_block)
18
60
  @react_to_block = react_to_block
19
61
  end
20
62
 
63
+ # Define methods and include modules for use by your behavior.
64
+ # helpers do
65
+ # include MyHelper
66
+ # def jump
67
+ # ...
68
+ # end
69
+ # end
70
+ #
21
71
  def helpers(&helpers_block)
22
72
  @helpers_block = helpers_block
23
73
  end
@@ -44,8 +44,15 @@ class BehaviorFactory
44
44
  add_behavior actor, beh unless actor.has_behavior?(beh)
45
45
  end
46
46
  end
47
- behavior.configure(opts)
47
+
48
+ behavior.opts = opts
48
49
  behavior.instance_eval &behavior_definition.setup_block if behavior_definition.setup_block
50
+
51
+ if behavior_definition.remove_block
52
+ behavior.define_singleton_method :remove, behavior_definition.remove_block
53
+ behavior.reacts_with :remove
54
+ end
55
+
49
56
  actor.add_behavior behavior_name, behavior
50
57
  end
51
58
  end
@@ -1,4 +1,6 @@
1
1
  module Gamebox
2
+ include GameboxDSL
3
+
2
4
  # Returns the global configuration object
3
5
  def self.configuration
4
6
  @configuration ||= Configuration.new
@@ -9,24 +11,6 @@ module Gamebox
9
11
  yield configuration if block_given?
10
12
  end
11
13
 
12
- def define_stage(name, &blk)
13
- Stage.define name, &blk
14
- end
15
-
16
- def define_behavior(name, &blk)
17
- Behavior.define name, &blk
18
- end
19
-
20
- def define_actor(name, &blk)
21
- Actor.define name, &blk
22
- end
23
-
24
- def define_actor_view(name, &blk)
25
- ActorView.define name, &blk
26
- end
27
-
28
- # module_function :define_behavior, :define_actor, :define_actor_view
29
-
30
14
 
31
15
  end
32
16
 
@@ -9,6 +9,8 @@ class Director
9
9
 
10
10
  def clear_subscriptions
11
11
  @subscriptions = Hash[@update_slots.map { |slot| [slot, []] }]
12
+ @new_subscriptions = []
13
+ @unsubscriptions = []
12
14
  end
13
15
 
14
16
  def pause
@@ -24,27 +26,36 @@ class Director
24
26
  end
25
27
 
26
28
  def when(event=:update, &callback)
27
- @subscriptions[event] ||= []
28
- @subscriptions[event] << callback
29
+ @new_subscriptions << [event, callback]
29
30
  end
30
31
 
31
32
  def update(time)
33
+ @new_subscriptions.each do |(event, callback)|
34
+ @subscriptions[event] ||= []
35
+ @subscriptions[event] << callback
36
+ end
37
+ @new_subscriptions.clear
38
+
39
+ @unsubscriptions.each do |listener|
40
+ for slot in @subscriptions.keys
41
+ @subscriptions[slot].delete_if do |block|
42
+ eval('self',block.binding).equal?(listener)
43
+ end
44
+ end
45
+ end
46
+ @unsubscriptions.clear
47
+
32
48
  time_in_seconds = time / 1000.to_f
33
49
  @update_slots.each do |slot|
34
50
  @subscriptions[slot].each do |callback|
35
51
  callback.call time, time_in_seconds
36
52
  end
37
53
  end
54
+
38
55
  end
39
56
 
40
57
  def unsubscribe_all(listener)
41
- if @subscriptions
42
- for slot in @subscriptions.keys
43
- @subscriptions[slot].delete_if do |block|
44
- eval('self',block.binding).equal?(listener)
45
- end
46
- end
47
- end
58
+ @unsubscriptions << listener
48
59
  end
49
60
 
50
61
  end
@@ -0,0 +1,129 @@
1
+ module GameboxDSL
2
+
3
+ # Defines a stage; a stage is a game mode. (ie :main_menu, :play, or :credits)
4
+ #
5
+ # Raises an erorr if the stage already exists
6
+ #
7
+ # define_stage :main_menu do
8
+ # # injects your dependencies; will construct if needed
9
+ # requires :input_manager, :customer_monkey_factory
10
+ #
11
+ # # callback for stage setup
12
+ # curtain_up &block
13
+ #
14
+ # # callback for stage teardown
15
+ # curtain_down &block
16
+ #
17
+ # # redefine the renderer for this stage, Gamebox has a default Renderer
18
+ # # if unspecified
19
+ # render_with :my_custom_renderer
20
+ #
21
+ # # define any helper methods and include any needed modules
22
+ # helpers &block
23
+ #
24
+ # end
25
+ #
26
+ # @see StageDefinition
27
+ # @see Stage
28
+ def define_stage(name, &blk)
29
+ Stage.define name, &blk
30
+ end
31
+
32
+ # Defines a behavior type. (ie :jumper or :shooter)
33
+ #
34
+ # Raises an erorr if the behavior already exists
35
+ #
36
+ # define_behavior :jumper do
37
+ # # injects your dependencies; will construct if needed
38
+ # requires :input_manager, :timer_manager, :stage
39
+ #
40
+ # # adds the required behaviors to your actor if not present
41
+ # # NOTE: no options can be passed to the added behavior
42
+ # required_behaviors :positioned
43
+ #
44
+ # # callback when your behavior has been added to an actor
45
+ # # #opts will be populated with any args that were specified on behavior
46
+ # # addition
47
+ # setup &block
48
+ #
49
+ # # callback when your behavior has been removed from an actor
50
+ # remove &block
51
+ #
52
+ # # define a custom handler for reacting to your actor's messages
53
+ # # @see Behavior#reacts_with for recommended message dispatch
54
+ # react_to &block
55
+ #
56
+ # # define any helper methods and include any needed modules
57
+ # helpers &block
58
+ #
59
+ # end
60
+ #
61
+ # @see BehaviorDefinition
62
+ # @see Behavior
63
+ def define_behavior(name, &blk)
64
+ Behavior.define name, &blk
65
+ end
66
+
67
+ # Defines an actor type, (ie :plumber). Optionally adding attributes, behaviors and a view.
68
+ #
69
+ # Raises an erorr if the actor already exists
70
+ #
71
+ # define_actor :plumber do
72
+ # # define default attributes and values
73
+ # has_attribute(s) x: 7, y: 12
74
+ #
75
+ # # define default behaviors and their options options can be
76
+ # # - list of behavior names
77
+ # # - hash of behavior names to options for each behavior
78
+ # # - block form
79
+ # has_behavior :postitioned
80
+ # has_behaviors do
81
+ # jumper max: 12, double: true
82
+ # end
83
+ #
84
+ # # Allows the inlining of one behavior in this actor.
85
+ # # It is equivalent to creating a behavior with the same name as the actor,
86
+ # # and adding it to the actor.
87
+ # #
88
+ # # The block works the same as calling #define_behavior.
89
+ # behavior
90
+ #
91
+ # # Allows the inline of a view in this actor
92
+ # # It is equivalent to creating an actor view with the same name as the actor.
93
+ # #
94
+ # # The block works the same as calling #define_actor_view.
95
+ # view
96
+ #
97
+ # end
98
+ #
99
+ # @see ActorDefinition
100
+ # @see Actor
101
+ def define_actor(name, &blk)
102
+ Actor.define name, &blk
103
+ end
104
+
105
+ # Defines an actor view type. (ie :plumber_view).
106
+ # Constructed when any actor with matching name is created
107
+ # ie: :ship_view will be created and shown for any actor :ship that is created
108
+ #
109
+ # Raises an erorr if the actor view already exists
110
+ #
111
+ # define_actor :plumber_view do
112
+ # # injects your dependencies; will construct if needed
113
+ # requires :input_manager, :customer_monkey_factory
114
+ #
115
+ # # callback when your view is created
116
+ # # #actor will be available at this time
117
+ # setup &block
118
+ #
119
+ # # define any helper methods and include any needed modules
120
+ # helpers &block
121
+ #
122
+ # end
123
+ #
124
+ # @see ActorViewDefinition
125
+ # @see ActorView
126
+ def define_actor_view(name, &blk)
127
+ ActorView.define name, &blk
128
+ end
129
+ end
@@ -19,8 +19,8 @@ else
19
19
  end
20
20
  end
21
21
 
22
- ZERO_VEC_2 = vec2(0,0)
22
+ ZERO_VEC_2 = vec2(0,0) unless defined? ZERO_VEC_2
23
23
 
24
24
  module Math
25
- HALF_PI = PI / 2.0
25
+ HALF_PI = PI / 2.0 unless defined? HALF_PI
26
26
  end
@@ -1,10 +1,11 @@
1
- class SpatialTreeStagehand < Stagehand
1
+ class SpatialTree
2
2
  extend Forwardable
3
3
  def_delegators :@tree, :calculate_bb, :to_s, :each, :collisions, :query, :valid?
4
4
 
5
- attr_reader :moved_items
5
+ attr_reader :moved_items, :stage
6
6
 
7
- def setup
7
+ def initialize(stage)
8
+ @stage
8
9
  @dead_actors = {}
9
10
  @moved_items = {}
10
11
  @tree = AABBTree.new
@@ -14,7 +14,6 @@ class Stage
14
14
  def configure(backstage, opts)
15
15
  viewport.reset
16
16
 
17
- @stagehands = {}
18
17
  @backstage = backstage
19
18
  @opts = opts
20
19
  renderer.clear_drawables
@@ -25,32 +24,6 @@ class Stage
25
24
  end
26
25
  alias :spawn :create_actor
27
26
 
28
- # extract all the params from a node that are needed to construct an actor
29
- def create_actors_from_svg svg_doc
30
- float_keys = ["x","y"]
31
- dynamic_actors ||= {}
32
- layer = svg_doc.find_group_by_label("actors")
33
-
34
- unless layer.nil?
35
- # each image in the layer is an actor
36
- layer.images.each do |actor_def|
37
- klass = actor_def.game_class.to_sym
38
- handle = actor_def.game_handle
39
- new_opts = {}
40
- actor_def.node.attributes.each do |k,v|
41
- v = v.to_f if float_keys.include? k
42
- new_opts[k.to_sym] = v
43
- end
44
-
45
- actor = create_actor klass, new_opts
46
- dynamic_actors[handle.to_sym] = actor if handle
47
- end
48
- end
49
- alias :spawn_from_svg :create_actors_from_svg
50
-
51
- dynamic_actors
52
- end
53
-
54
27
  def draw(target)
55
28
  renderer.draw target
56
29
  end
@@ -58,9 +31,6 @@ class Stage
58
31
  def update(time)
59
32
  director.update time
60
33
  viewport.update time
61
- @stagehands.each do |name, stagehand|
62
- stagehand.update time
63
- end
64
34
  find_collisions
65
35
  timer_manager.update time
66
36
  end
@@ -107,10 +77,6 @@ class Stage
107
77
  @paused = true
108
78
  end
109
79
 
110
- def stagehand(stagehand_sym, opts={})
111
- @stagehands[stagehand_sym] ||= create_stagehand(stagehand_sym, opts)
112
- end
113
-
114
80
  # pauses the current stage, creates an actor using args, unpauses on actor death
115
81
  #
116
82
  # Example:
@@ -129,11 +95,6 @@ class Stage
129
95
  end
130
96
 
131
97
  private
132
- def create_stagehand(name, opts)
133
- underscored_class = "#{name}_stagehand"
134
- klass = ClassFinder.find underscored_class
135
- klass.new self, opts
136
- end
137
98
 
138
99
  class << self
139
100
 
@@ -4,56 +4,57 @@ class StageDefinition
4
4
 
5
5
  # Required objects that you need for your specific stage
6
6
  # The objects will be created for you.
7
- # example:
7
+ #
8
8
  # define_stage :main_menu do
9
- # require :magic_thinger
9
+ # requires :magic_thinger
10
10
  # end
11
11
  def requires(*injections_needed)
12
- # kid.construct_with *self.object_definition.component_names
13
12
  @required_injections = injections_needed
14
13
  end
15
14
 
16
15
  # Define a block of code to run when your stage is and ready to play
17
- # example:
18
- # define_stage :main_menu do
19
- # curtain_up do
20
- # @info = load_some_info
21
- # end
22
- # end
16
+ #
17
+ # define_stage :main_menu do
18
+ # curtain_up do
19
+ # @info = load_some_info
20
+ # end
21
+ # end
23
22
  def curtain_up(&curtain_up_block)
24
23
  @curtain_up_block = curtain_up_block
25
24
  end
26
25
 
27
26
  # Define a block of code to run when your stage has been shutdown
28
- # example:
29
- # define_stage :main_menu do
30
- # curtain_down do
31
- # @info = load_some_info
32
- # end
33
- # end
27
+ #
28
+ # define_stage :main_menu do
29
+ # curtain_down do
30
+ # @info = load_some_info
31
+ # end
32
+ # end
34
33
  def curtain_down(&curtain_down_block)
35
34
  @curtain_down_block = curtain_down_block
36
35
  end
37
36
 
38
37
  # Replaces the default renderer with your own.
39
- # example:
40
- # define_stage :main_menu do
41
- # render_with :my_render
42
- # ...
43
- # end
38
+ #
39
+ # define_stage :main_menu do
40
+ # render_with :my_render
41
+ # ...
42
+ # end
44
43
  def render_with(render_class_name)
45
44
  @renderer = render_class_name
46
45
  end
47
46
 
48
47
  # Define any helper methods / include modules here
49
48
  # These will be available for curtain_up / update / draw to use.
50
- # example:
51
- # define_stage :main_menu do
52
- # include MinMaxHelpers
53
- # def calculate_thinger
54
- # ...
55
- # end
56
- # end
49
+ #
50
+ # define_stage :main_menu do
51
+ # helpers do
52
+ # include MinMaxHelpers
53
+ # def calculate_thinger
54
+ # ...
55
+ # end
56
+ # end
57
+ # end
57
58
  def helpers(&helpers_block)
58
59
  @helpers_block = helpers_block
59
60
  end
@@ -24,6 +24,17 @@ module ObservableAttributes
24
24
  end
25
25
  end
26
26
 
27
+ # Adds attributes that are not currently set.
28
+ # Takes a list of symbols or a hash of symbols => default values
29
+ #
30
+ # examples:
31
+ #
32
+ # foo.has_attributes :x, :y
33
+ # # adds x, x=, y, y= methods
34
+ # #fires events x_changed, y_changed when the values change
35
+ #
36
+ # foo.has_attributes x: 5, y: 3
37
+ # # this form provides default values if these are new attributes
27
38
  def has_attributes(*names)
28
39
  if names.first.is_a? Hash
29
40
  names.first.each do |name, default|
@@ -36,6 +47,8 @@ module ObservableAttributes
36
47
  end
37
48
  end
38
49
 
50
+ # singular form of has_attributes
51
+ # takes the symbol name and an optional default value
39
52
  def has_attribute(name, value=nil)
40
53
  @evented_attributes ||= []
41
54
  unless has_attribute? name
@@ -48,10 +61,12 @@ module ObservableAttributes
48
61
  end
49
62
  end
50
63
 
64
+ # Returns true if the passed in symbol is an attr on this object
51
65
  def has_attribute?(name)
52
66
  @evented_attributes && @evented_attributes.include?(name)
53
67
  end
54
68
 
69
+ # Returns a new hash containing the attr keys and values
55
70
  def attributes
56
71
  {}.tap do |atts|
57
72
  if @evented_attributes
@@ -193,6 +193,7 @@ class Vector2
193
193
  # of error to compensate for floating point imprecision).
194
194
  #
195
195
  def ==( vector )
196
+ return false if vector.nil?
196
197
  _nearly_equal?(@x, vector.at(0)) and _nearly_equal?(@y, vector.at(1))
197
198
  end
198
199
 
@@ -201,23 +202,29 @@ class Vector2
201
202
  # [x,y] Array.
202
203
  #
203
204
  def []( index )
204
- [@x, @y][index]
205
+ case index
206
+ when 0
207
+ @x
208
+ when 1
209
+ @y
210
+ else
211
+ nil
212
+ end
205
213
  end
206
214
 
207
215
  alias :at :[]
208
216
 
209
217
 
210
218
  def hash # :nodoc:
211
- @hash ||= (((@x - @x.modulo(1E-10)).hash << 2) +
212
- ((@y - @y.modulo(1E-10)).hash << 1) +
213
- self.class.hash)
219
+ @hash ||= [@x, @y, self.class].hash
214
220
  end
215
221
 
216
222
 
217
223
  # Iterates over this vector as if it were an [x,y] Array.
218
224
  #
219
- def each( &block )
220
- [@x, @y].each( &block )
225
+ def each
226
+ yield @x
227
+ yield @y
221
228
  end
222
229
 
223
230
 
@@ -33,6 +33,7 @@ module GameboxSpecHelpers
33
33
  @_req_mocks = create_mocks(*reqs)
34
34
  }
35
35
  let (:opts) { {} }
36
+ let (:actor) { @actor }
36
37
  subject {
37
38
 
38
39
  # TODO so much duplication here from the *Factories
@@ -61,7 +62,7 @@ module GameboxSpecHelpers
61
62
  # _add_behavior actor, beh unless actor.has_behavior?(beh)
62
63
  # end
63
64
  # end
64
- behavior.configure(opts)
65
+ behavior.opts = opts
65
66
  behavior.instance_eval &@behavior_definition.setup_block if @behavior_definition.setup_block
66
67
  end
67
68
  }
@@ -2,7 +2,7 @@ module Gamebox
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 4
5
- TINY = 0
5
+ TINY = 1
6
6
  RC = 0
7
7
 
8
8
  if RC > 0
@@ -27,7 +27,7 @@ end
27
27
  NUM = 1_000
28
28
  Benchmark.bm(60) do |b|
29
29
  b.report("full") do
30
- tree = SpatialTreeStagehand.new :thing, :thing
30
+ tree = SpatialTree.new :thing
31
31
 
32
32
  thing = BoxedActor.new 1, 2, 3, 4
33
33
  tree.add thing
@@ -30,11 +30,11 @@ describe :label do
30
30
  @font_style_factory.stubs(:build).with('fonty.ttf', 22, :red).returns(:stylish_font)
31
31
  @actor.expects(:has_attributes).with(font_style: :stylish_font)
32
32
 
33
- subject.setup
33
+ subject
34
34
  end
35
35
 
36
36
  it 'listens for text changes' do
37
- subject.setup
37
+ subject
38
38
  @actor.stubs(text: "foo")
39
39
 
40
40
  font_style = stub(height: 13)
@@ -48,7 +48,7 @@ describe :label do
48
48
  end
49
49
 
50
50
  it 'listens for font color changes' do
51
- subject.setup
51
+ subject
52
52
  font_style = stub
53
53
  font_style.expects(:color=).with(:red)
54
54
  @actor.stubs(font_style: font_style, color: :red)
@@ -57,7 +57,7 @@ describe :label do
57
57
  end
58
58
 
59
59
  it 'listens for font name changes' do
60
- subject.setup
60
+ subject
61
61
  @actor.stubs(text: "foo", font_name: "asimov.ttf")
62
62
 
63
63
  font_style = stub(height: 13)
@@ -74,7 +74,7 @@ describe :label do
74
74
  end
75
75
 
76
76
  it 'listens for font size changes' do
77
- subject.setup
77
+ subject
78
78
  @actor.stubs(text: "foo", font_size: 14)
79
79
 
80
80
  font_style = stub(height: 13)
@@ -4,18 +4,18 @@ describe BehaviorFactory do
4
4
  let(:some_behavior) { stub('some behavior', required_behaviors: []) }
5
5
  let(:object_context) { mock('object context') }
6
6
  let(:some_actor) { stub('some actor', add_behavior: nil, this_object_context: object_context) }
7
+ let(:some_block) { Proc.new }
7
8
 
8
9
  before do
9
10
  Behavior.define :shootable
10
-
11
11
  object_context.stubs(:[]).with(:behavior).returns(some_behavior)
12
12
  object_context.stubs(:in_subcontext).yields(object_context)
13
- some_behavior.stubs(:configure)
13
+ some_behavior.stubs(:opts=)
14
14
  end
15
15
 
16
16
  describe "#add_behavior" do
17
17
  it 'creates the behavior based on the actor and symbol behavior_def' do
18
- some_behavior.expects(:configure).with({})
18
+ some_behavior.expects(:opts=).with({})
19
19
 
20
20
  subject.add_behavior some_actor, :shootable
21
21
  end
@@ -27,7 +27,7 @@ describe BehaviorFactory do
27
27
 
28
28
  it 'configures the behavior with the given opts' do
29
29
  opts = {some: 'opts'}
30
- some_behavior.expects(:configure).with(opts)
30
+ some_behavior.expects(:opts=).with(opts)
31
31
 
32
32
  subject.add_behavior some_actor, :shootable, opts
33
33
  end
@@ -5,6 +5,9 @@ describe Behavior do
5
5
 
6
6
  it 'should auto-require behaviors that it depends on'
7
7
  it 'has default react_to impl'
8
+ describe "#reacts_with" do
9
+ it 'adds together reactions for multiple calls'
10
+ end
8
11
  describe "#add_behavior" do
9
12
  it 'uses the behavior factory to add the behavior to the actor'
10
13
  end
@@ -1,7 +1,7 @@
1
1
  require 'helper'
2
2
 
3
- describe SpatialTreeStagehand do
4
- subject { SpatialTreeStagehand.new :stage, {} }
3
+ describe SpatialTree do
4
+ subject { SpatialTree.new :stage }
5
5
  let(:tree) { stub('tree') }
6
6
 
7
7
  before do
@@ -53,7 +53,6 @@ describe Stage do
53
53
  subject.update(:time)
54
54
  end
55
55
 
56
- it 'updates stagehands'
57
56
  it 'checks for collisions'
58
57
  end
59
58
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gamebox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-04-28 00:00:00.000000000 Z
14
+ date: 2013-07-25 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: gosu
@@ -401,6 +401,7 @@ files:
401
401
  - lib/gamebox/core/font_style.rb
402
402
  - lib/gamebox/core/font_style_factory.rb
403
403
  - lib/gamebox/core/game.rb
404
+ - lib/gamebox/core/gamebox_dsl.rb
404
405
  - lib/gamebox/core/hooked_gosu_window.rb
405
406
  - lib/gamebox/core/input_manager.rb
406
407
  - lib/gamebox/core/input_mapper.rb
@@ -409,16 +410,15 @@ files:
409
410
  - lib/gamebox/core/renderer.rb
410
411
  - lib/gamebox/core/resource_manager.rb
411
412
  - lib/gamebox/core/sound_manager.rb
413
+ - lib/gamebox/core/spatial_tree.rb
412
414
  - lib/gamebox/core/stage.rb
413
415
  - lib/gamebox/core/stage_definition.rb
414
416
  - lib/gamebox/core/stage_factory.rb
415
417
  - lib/gamebox/core/stage_manager.rb
416
- - lib/gamebox/core/stagehand.rb
417
418
  - lib/gamebox/core/svg_document.rb
418
419
  - lib/gamebox/core/timer_manager.rb
419
420
  - lib/gamebox/core/viewport.rb
420
421
  - lib/gamebox/core/wrapped_screen.rb
421
- - lib/gamebox/data/config/objects.yml
422
422
  - lib/gamebox/data/fonts/Asimov.ttf
423
423
  - lib/gamebox/data/fonts/GAMEBOX_FONTS_GO_HERE
424
424
  - lib/gamebox/data/graphics/GAMEBOX_GRAPHICS_GO_HERE
@@ -448,7 +448,6 @@ files:
448
448
  - lib/gamebox/post_setup_handlers/gamebox_debug_helpers.rb
449
449
  - lib/gamebox/post_setup_handlers/pry_remote_server.rb
450
450
  - lib/gamebox/spec/helper.rb
451
- - lib/gamebox/stagehands/spatial_tree_stagehand.rb
452
451
  - lib/gamebox/tasks/gamebox_tasks.rake
453
452
  - lib/gamebox/version.rb
454
453
  - lib/gamebox/views/graphical_actor_view.rb
@@ -491,6 +490,7 @@ files:
491
490
  - spec/core/physics_manager_spec.rb
492
491
  - spec/core/renderer_spec.rb
493
492
  - spec/core/resource_manager_spec.rb
493
+ - spec/core/spatial_tree_spec.rb
494
494
  - spec/core/stage_definition_spec.rb
495
495
  - spec/core/stage_manager_spec.rb
496
496
  - spec/core/stage_spec.rb
@@ -504,7 +504,6 @@ files:
504
504
  - spec/fixtures/snelpling/jump/3.png
505
505
  - spec/helper.rb
506
506
  - spec/lib/class_finder_spec.rb
507
- - spec/stagehands/spatial_tree_stagehand_spec.rb
508
507
  - spec/views/graphical_actor_view_spec.rb
509
508
  - templates/actor_template.erb
510
509
  - templates/app/.gitignore
@@ -539,7 +538,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
539
538
  version: '0'
540
539
  segments:
541
540
  - 0
542
- hash: -3641316874806944504
541
+ hash: 3939132703427340795
543
542
  required_rubygems_version: !ruby/object:Gem::Requirement
544
543
  none: false
545
544
  requirements:
@@ -548,7 +547,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
548
547
  version: '0'
549
548
  segments:
550
549
  - 0
551
- hash: -3641316874806944504
550
+ hash: 3939132703427340795
552
551
  requirements: []
553
552
  rubyforge_project: gamebox
554
553
  rubygems_version: 1.8.25
@@ -589,6 +588,7 @@ test_files:
589
588
  - spec/core/physics_manager_spec.rb
590
589
  - spec/core/renderer_spec.rb
591
590
  - spec/core/resource_manager_spec.rb
591
+ - spec/core/spatial_tree_spec.rb
592
592
  - spec/core/stage_definition_spec.rb
593
593
  - spec/core/stage_manager_spec.rb
594
594
  - spec/core/stage_spec.rb
@@ -602,5 +602,4 @@ test_files:
602
602
  - spec/fixtures/snelpling/jump/3.png
603
603
  - spec/helper.rb
604
604
  - spec/lib/class_finder_spec.rb
605
- - spec/stagehands/spatial_tree_stagehand_spec.rb
606
605
  - spec/views/graphical_actor_view_spec.rb
@@ -1,14 +0,0 @@
1
- class Stagehand
2
- attr_accessor :opts, :stage
3
- def initialize(stage, opts)
4
- @stage = stage
5
- @opts = opts
6
- setup
7
- end
8
-
9
- def setup
10
- end
11
-
12
- def update(time)
13
- end
14
- end
@@ -1,39 +0,0 @@
1
- game:
2
- compose:
3
- - wrapped_screen
4
- - input_manager
5
- - sound_manager
6
- - stage_manager
7
- resource_manager:
8
- auto_require: false
9
- compose:
10
- - wrapped_screen
11
- stage_manager:
12
- auto_require: false
13
- compose:
14
- - input_manager
15
- - resource_manager
16
- - sound_manager
17
- - config_manager
18
- - actor_factory
19
- sound_manager:
20
- auto_require: false
21
- compose:
22
- - resource_manager
23
- - config_manager
24
- input_manager:
25
- auto_require: false
26
- compose:
27
- - wrapped_screen
28
- - config_manager
29
- wrapped_screen:
30
- auto_require: false
31
- compose:
32
- - config_manager
33
- config_manager:
34
- auto_require: false
35
- actor_factory:
36
- auto_require: false
37
- compose:
38
- - input_manager
39
- - wrapped_screen