gamebox 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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