gamebox 0.4.0.rc5 → 0.4.0.rc11

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.
Files changed (93) hide show
  1. data/README.md +205 -127
  2. data/bin/gamebox +49 -3
  3. data/bin/gb +87 -0
  4. data/gamebox.gemspec +4 -3
  5. data/lib/gamebox.rb +1 -1
  6. data/lib/gamebox/actors/collidable_debugger.rb +4 -4
  7. data/lib/gamebox/actors/icon.rb +7 -0
  8. data/lib/gamebox/actors/label.rb +41 -42
  9. data/lib/gamebox/behaviors/animated.rb +6 -0
  10. data/lib/gamebox/behaviors/audible.rb +1 -2
  11. data/lib/gamebox/behaviors/collidable.rb +1 -1
  12. data/lib/gamebox/behaviors/graphical.rb +8 -4
  13. data/lib/gamebox/behaviors/physical.rb +6 -1
  14. data/lib/gamebox/behaviors/positioned.rb +4 -11
  15. data/lib/gamebox/behaviors/projectile.rb +8 -0
  16. data/lib/gamebox/behaviors/visible.rb +3 -3
  17. data/lib/gamebox/core/aabb_tree.rb +1 -1
  18. data/lib/gamebox/core/actor.rb +37 -50
  19. data/lib/gamebox/core/actor_definition.rb +41 -0
  20. data/lib/gamebox/core/actor_view.rb +6 -21
  21. data/lib/gamebox/core/actor_view_definition.rb +19 -0
  22. data/lib/gamebox/core/actor_view_factory.rb +9 -3
  23. data/lib/gamebox/core/behavior.rb +8 -27
  24. data/lib/gamebox/core/behavior_definition.rb +24 -0
  25. data/lib/gamebox/core/config_manager.rb +45 -30
  26. data/lib/gamebox/core/configuration.rb +5 -0
  27. data/lib/gamebox/core/core.rb +4 -0
  28. data/lib/gamebox/core/debug_helpers.rb +46 -0
  29. data/lib/gamebox/core/director.rb +32 -5
  30. data/lib/gamebox/core/event_symbols.rb +214 -0
  31. data/lib/gamebox/core/game.rb +1 -1
  32. data/lib/gamebox/core/input_manager.rb +1 -4
  33. data/lib/gamebox/core/input_mapper.rb +85 -0
  34. data/lib/gamebox/core/physics.rb +7 -3
  35. data/lib/gamebox/core/physics_manager.rb +5 -1
  36. data/lib/gamebox/core/renderer.rb +72 -0
  37. data/lib/gamebox/core/stage.rb +25 -81
  38. data/lib/gamebox/core/stage_definition.rb +60 -0
  39. data/lib/gamebox/core/stage_factory.rb +56 -0
  40. data/lib/gamebox/core/stage_manager.rb +5 -11
  41. data/lib/gamebox/core/timer_manager.rb +6 -2
  42. data/lib/gamebox/core/viewport.rb +12 -5
  43. data/lib/gamebox/core/wrapped_screen.rb +8 -5
  44. data/lib/gamebox/gamebox_application.rb +21 -19
  45. data/lib/gamebox/lib/array_ext.rb +9 -0
  46. data/lib/gamebox/lib/observable_attributes.rb +24 -0
  47. data/lib/gamebox/lib/vector2.rb +432 -0
  48. data/lib/gamebox/post_setup_handlers/file_watcher.rb +37 -0
  49. data/lib/gamebox/post_setup_handlers/gamebox_debug_helpers.rb +13 -0
  50. data/lib/gamebox/post_setup_handlers/pry_remote_server.rb +29 -0
  51. data/lib/gamebox/spec/helper.rb +165 -17
  52. data/lib/gamebox/tasks/gamebox_tasks.rake +27 -12
  53. data/lib/gamebox/version.rb +1 -1
  54. data/lib/gamebox/views/graphical_actor_view.rb +4 -5
  55. data/script/perf_aabb.rb +13 -8
  56. data/spec/acceptance/animation_spec.rb +1 -3
  57. data/spec/acceptance/basic_actor_lifecycle_spec.rb +1 -1
  58. data/spec/acceptance/fps_actor_spec.rb +8 -12
  59. data/spec/acceptance/input_mapper_spec.rb +17 -24
  60. data/spec/acceptance/update_ordering_spec.rb +64 -0
  61. data/spec/actors/label_spec.rb +90 -5
  62. data/spec/behaviors/animated_spec.rb +1 -1
  63. data/spec/behaviors/collidable_spec.rb +7 -15
  64. data/spec/behaviors/positioned_spec.rb +12 -5
  65. data/spec/core/actor_spec.rb +31 -3
  66. data/spec/core/actor_view_spec.rb +1 -1
  67. data/spec/core/behavior_spec.rb +3 -0
  68. data/spec/core/configuration_spec.rb +49 -2
  69. data/spec/core/input_mapper_spec.rb +7 -0
  70. data/spec/core/renderer_spec.rb +89 -0
  71. data/spec/core/stage_definition_spec.rb +41 -0
  72. data/spec/core/stage_manager_spec.rb +11 -11
  73. data/spec/core/stage_spec.rb +38 -78
  74. data/spec/core/viewport_spec.rb +5 -2
  75. data/spec/core/wrapped_screen_spec.rb +18 -12
  76. data/spec/views/graphical_actor_view_spec.rb +33 -62
  77. data/templates/actor_template.erb +11 -0
  78. data/templates/app/README.md +1 -0
  79. data/templates/app/src/actors/{player.rb → player_actor.rb} +3 -1
  80. data/templates/app/src/behaviors/.gitkeep +0 -0
  81. data/templates/app/src/stages/demo_stage.rb +14 -0
  82. data/templates/behavior_template.erb +13 -0
  83. data/templates/stage_template.erb +13 -0
  84. metadata +60 -21
  85. data/component_generators/actor_generator.rb +0 -17
  86. data/lib/gamebox/actors/emitter.rb +0 -12
  87. data/lib/gamebox/behaviors/emitting.rb +0 -48
  88. data/lib/gamebox/behaviors/input_mapper.rb +0 -11
  89. data/lib/gamebox/lib/ftor.rb +0 -372
  90. data/spec/actors/emitter_spec.rb +0 -5
  91. data/templates/app/NEXT_STEPS.txt +0 -1
  92. data/templates/app/README.rdoc +0 -24
  93. data/templates/app/src/demo_stage.rb +0 -7
@@ -2,7 +2,7 @@ class Game
2
2
 
3
3
  # BTW: we have extra deps to make sure they are all built at game construction time
4
4
  construct_with :wrapped_screen, :input_manager, :sound_manager,
5
- :stage_manager
5
+ :stage_manager, :config_manager
6
6
 
7
7
  def configure
8
8
  stage_manager.change_stage_to stage_manager.default_stage
@@ -1,8 +1,5 @@
1
1
  require 'publisher'
2
2
 
3
- # looks like theres a bug in Gosu
4
- KbRangeBegin = 0
5
-
6
3
  # InputManager handles the pumping for events and distributing of said events.
7
4
  # You can gain access to these events by registering for all events,
8
5
  # or just the ones you care about.
@@ -25,7 +22,7 @@ class InputManager
25
22
  DOWN_EVENTS = [:mouse_down, :keyboard_down, :game_pad_down]
26
23
  UP_EVENTS = [:mouse_up, :keyboard_up, :game_pad_up]
27
24
 
28
- attr_accessor :window
25
+ attr_accessor :window, :down_ids
29
26
  construct_with :config_manager, :wrapped_screen
30
27
 
31
28
  # Sets up the clock and main event loop. You should never call this method,
@@ -0,0 +1,85 @@
1
+ class InputMapper
2
+ extend Publisher
3
+ can_fire_anything
4
+
5
+ construct_with :input_manager
6
+ def initialize
7
+ @action_ids = {}
8
+ end
9
+
10
+ # map_input is to be setup outside of an actor and passed in at construction
11
+ # time ie:
12
+ #
13
+ # mapper.map_input {
14
+ # '+a' => :jump, # emit jump when 'a' is _pressed_
15
+ # '-b' => :duck, # emit duck when 'b' is _released_
16
+ # 'c' => :block # emit block when 'c' is _pressed_ AND _released_
17
+ # }
18
+ #
19
+ # all keys will have a <key_name>? defined for checking state at anytime
20
+ # create_actor :fighter, input: mapper
21
+ #
22
+ # all of the actor's behaviors can / should use the input mapper instead of raw key bindings
23
+ def map_input(input_hash)
24
+ input_hash.each do |input, actions|
25
+ if input.start_with? '-'
26
+ register_key_released(input[1..-1], actions)
27
+ elsif input.start_with? '+'
28
+ register_key_pressed(input[1..-1], actions)
29
+ else
30
+ register_key_released(input, actions)
31
+ register_key_pressed(input, actions)
32
+ end
33
+ end
34
+ end
35
+
36
+ # unsubscribes for all input
37
+ def clear
38
+ input_manager.unsubscribe_all
39
+ end
40
+
41
+ def method_missing(name, *args)
42
+ if name.to_s.end_with? '?'
43
+ button_syms = @action_ids[name[0..-2].to_sym]
44
+ if button_syms
45
+ return button_syms.any? do |button_sym|
46
+ input_manager.down_ids.include? BUTTON_SYM_TO_ID[button_sym]
47
+ end
48
+ end
49
+ end
50
+
51
+ false
52
+ end
53
+
54
+ private
55
+ def register_key_pressed(key, actions)
56
+ id = BUTTON_SYM_TO_ID[key.to_sym]
57
+ raise "unknown button id from #{key}" unless id
58
+
59
+ input_manager.reg :down, id do |*args|
60
+ Array.wrap(actions).each do |action|
61
+ fire action, *args
62
+ end
63
+ end
64
+ def_state_probe_method(key, actions)
65
+ end
66
+
67
+ def register_key_released(key, actions)
68
+ id = BUTTON_SYM_TO_ID[key.to_sym]
69
+ raise "unknown button id from #{key}" unless id
70
+ input_manager.reg :up, id do |*args|
71
+ Array.wrap(actions).each do |action|
72
+ fire action, *args
73
+ end
74
+ end
75
+
76
+ def_state_probe_method(key, actions)
77
+ end
78
+
79
+ def def_state_probe_method(key, actions)
80
+ Array.wrap(actions).each do |action|
81
+ @action_ids[action] ||= []
82
+ @action_ids[action] << key.to_sym
83
+ end
84
+ end
85
+ end
@@ -1,5 +1,4 @@
1
1
  if defined? CP
2
- ZERO_VEC_2 = vec2(0,0) unless defined? ZERO_VEC_2
3
2
  def vec2(*args)
4
3
  CP::Vec2.new *args
5
4
  end
@@ -15,8 +14,13 @@ if defined? CP
15
14
  end
16
15
 
17
16
  else
18
- ZERO_VEC_2 = Ftor.new(0,0)
19
17
  def vec2(*args)
20
- Ftor.new *args
18
+ Vector2.new *args
21
19
  end
22
20
  end
21
+
22
+ ZERO_VEC_2 = vec2(0,0)
23
+
24
+ module Math
25
+ HALF_PI = PI / 2.0
26
+ end
@@ -4,9 +4,13 @@ class PhysicsManager
4
4
  def_delegators( :@space,
5
5
  :damping, :damping=,
6
6
  :gravity, :gravity=,
7
- :iterations, :iterations= )
7
+ :iterations, :iterations=,
8
+ :on_post_step, :add_post_step_callback
9
+ )
8
10
 
9
11
  attr_accessor :space
12
+ delegate 'add_post_step_callback' => '@space'
13
+
10
14
 
11
15
  # Time per physics step, in milliseconds (default 15). Small steps
12
16
  # make the simulation more stable than large steps, but if the step
@@ -0,0 +1,72 @@
1
+ class Renderer
2
+ construct_with :viewport
3
+
4
+ def initialize
5
+ clear_drawables
6
+ end
7
+
8
+ def register_drawable(drawable)
9
+ layer = drawable.layer
10
+ parallax = drawable.parallax
11
+ unless @drawables[parallax]
12
+ @drawables[parallax] = {}
13
+ @parallax_layers = @drawables.keys.sort.reverse
14
+ end
15
+ unless @drawables[parallax][layer]
16
+ @drawables[parallax][layer] = []
17
+ @layer_orders[parallax] = @drawables[parallax].keys.sort
18
+ end
19
+ @drawables[parallax][layer] << drawable
20
+ end
21
+
22
+
23
+ def unregister_drawable(drawable)
24
+ @drawables[drawable.parallax][drawable.layer].delete drawable
25
+ end
26
+
27
+ def clear_drawables
28
+ @drawables = {}
29
+ @layer_orders = {}
30
+ @parallax_layers = []
31
+ end
32
+
33
+
34
+ def draw(target)
35
+ center_x = viewport.width / 2
36
+ center_y = viewport.height / 2
37
+
38
+ target.rotate(-viewport.rotation, center_x, center_y) do
39
+ z = 0
40
+ @parallax_layers.each do |parallax_layer|
41
+ drawables_on_parallax_layer = @drawables[parallax_layer]
42
+
43
+ if drawables_on_parallax_layer
44
+ @layer_orders[parallax_layer].each do |layer|
45
+
46
+ trans_x = viewport.x_offset parallax_layer
47
+ trans_y = viewport.y_offset parallax_layer
48
+
49
+ z += 1
50
+ drawables_on_parallax_layer[layer].each do |drawable|
51
+ drawable.draw target, trans_x, trans_y, z
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ # move all actors from one layer to another
60
+ # note, this will remove all actors in that layer!
61
+ def move_layer(from_parallax, from_layer, to_parallax, to_layer)
62
+ drawable_list = @drawables[from_parallax][from_layer].dup
63
+
64
+ drawable_list.each do |drawable|
65
+ unregister_drawable drawable
66
+ drawable.parallax = to_parallax
67
+ drawable.layer = to_layer
68
+ register_drawable drawable
69
+ end
70
+ end
71
+
72
+ end
@@ -7,28 +7,17 @@ class Stage
7
7
 
8
8
  construct_with :input_manager, :actor_factory, :resource_manager,
9
9
  :sound_manager, :config_manager, :director, :timer_manager,
10
- :this_object_context
10
+ :viewport, :this_object_context
11
11
 
12
- def self.inherited(kid)
13
- kid.construct_with *self.object_definition.component_names
14
- end
15
-
16
- attr_accessor :opts, :viewport, :backstage
12
+ attr_accessor :opts, :backstage
17
13
 
18
14
  def configure(backstage, opts)
19
- res = config_manager[:screen_resolution]
20
- @viewport = Viewport.new res[0], res[1]
21
- this_object_context[:viewport] = @viewport
15
+ viewport.reset
22
16
 
23
17
  @stagehands = {}
24
18
  @backstage = backstage
25
19
  @opts = opts
26
-
27
- setup
28
- end
29
-
30
- def setup
31
- clear_drawables
20
+ renderer.clear_drawables
32
21
  end
33
22
 
34
23
  def create_actor(type, args={})
@@ -61,10 +50,14 @@ class Stage
61
50
 
62
51
  dynamic_actors
63
52
  end
53
+
54
+ def draw(target)
55
+ renderer.draw target
56
+ end
64
57
 
65
58
  def update(time)
66
59
  director.update time
67
- @viewport.update time
60
+ viewport.update time
68
61
  @stagehands.each do |name, stagehand|
69
62
  stagehand.update time
70
63
  end
@@ -72,77 +65,12 @@ class Stage
72
65
  timer_manager.update time
73
66
  end
74
67
 
75
- def curtain_raising(*args)
76
- curtain_up *args
77
- end
78
-
79
- def curtain_dropping(*args)
80
- curtain_down *args
81
- end
82
-
83
68
  def curtain_up(*args)
84
69
  end
85
70
 
86
71
  def curtain_down(*args)
87
72
  end
88
73
 
89
- def draw(target)
90
- z = 0
91
- @parallax_layers.each do |parallax_layer|
92
- drawables_on_parallax_layer = @drawables[parallax_layer]
93
-
94
- if drawables_on_parallax_layer
95
- @layer_orders[parallax_layer].each do |layer|
96
-
97
- trans_x = @viewport.x_offset parallax_layer
98
- trans_y = @viewport.y_offset parallax_layer
99
-
100
- z += 1
101
- drawables_on_parallax_layer[layer].each do |drawable|
102
- drawable.draw target, trans_x, trans_y, z
103
- end
104
- end
105
- end
106
- end
107
- end
108
-
109
- def unregister_drawable(drawable)
110
- @drawables[drawable.parallax][drawable.layer].delete drawable
111
- end
112
-
113
- def clear_drawables
114
- @drawables = {}
115
- @layer_orders = {}
116
- @parallax_layers = []
117
- end
118
-
119
- def register_drawable(drawable)
120
- layer = drawable.layer
121
- parallax = drawable.parallax
122
- unless @drawables[parallax]
123
- @drawables[parallax] = {}
124
- @parallax_layers = @drawables.keys.sort.reverse
125
- end
126
- unless @drawables[parallax][layer]
127
- @drawables[parallax][layer] = []
128
- @layer_orders[parallax] = @drawables[parallax].keys.sort
129
- end
130
- @drawables[parallax][layer] << drawable
131
- end
132
-
133
- # move all actors from one layer to another
134
- # note, this will remove all actors in that layer!
135
- def move_layer(from_parallax, from_layer, to_parallax, to_layer)
136
- drawable_list = @drawables[from_parallax][from_layer].dup
137
-
138
- drawable_list.each do |drawable|
139
- unregister_drawable drawable
140
- drawable.parallax = to_parallax
141
- drawable.layer = to_layer
142
- register_drawable drawable
143
- end
144
- end
145
-
146
74
  def on_pause(&block)
147
75
  @pause_listeners ||= []
148
76
  @pause_listeners << block if block_given?
@@ -207,6 +135,22 @@ class Stage
207
135
  klass.new self, opts
208
136
  end
209
137
 
138
+ class << self
139
+
140
+ def define(stage_name, opts={}, &blk)
141
+ @definitions ||= {}
142
+ raise "Stage [#{stage_name}] already defined at #{@definitions[stage_name].source}" if @definitions[stage_name]
143
+
144
+ definition = StageDefinition.new
145
+ definition.source = caller.detect{|c|!c.match /core/}
146
+ definition.instance_eval &blk if block_given?
147
+ @definitions[stage_name] = definition
148
+ end
149
+
150
+ def definitions
151
+ @definitions ||= {}
152
+ end
153
+ end
210
154
 
211
155
  end
212
156
 
@@ -0,0 +1,60 @@
1
+ class StageDefinition
2
+ attr_accessor :curtain_up_block, :curtain_down_block, :renderer,
3
+ :helpers_block, :required_injections, :source
4
+
5
+ # Required objects that you need for your specific stage
6
+ # The objects will be created for you.
7
+ # example:
8
+ # define_stage :main_menu do
9
+ # require :magic_thinger
10
+ # end
11
+ def requires(*injections_needed)
12
+ # kid.construct_with *self.object_definition.component_names
13
+ @required_injections = injections_needed
14
+ end
15
+
16
+ # 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
23
+ def curtain_up(&curtain_up_block)
24
+ @curtain_up_block = curtain_up_block
25
+ end
26
+
27
+ # 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
34
+ def curtain_down(&curtain_down_block)
35
+ @curtain_down_block = curtain_down_block
36
+ end
37
+
38
+ # Replaces the default renderer with your own.
39
+ # example:
40
+ # define_stage :main_menu do
41
+ # render_with :my_render
42
+ # ...
43
+ # end
44
+ def render_with(render_class_name)
45
+ @renderer = render_class_name
46
+ end
47
+
48
+ # Define any helper methods / include modules here
49
+ # 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
57
+ def helpers(&helpers_block)
58
+ @helpers_block = helpers_block
59
+ end
60
+ end
@@ -0,0 +1,56 @@
1
+ class StageFactory
2
+ construct_with :this_object_context, :backstage
3
+
4
+ def build(stage_name, opts={})
5
+ this_object_context.in_subcontext do |stage_context|
6
+ begin
7
+ stage_context[:stage].tap do |stage|
8
+
9
+ stage_definition = Stage.definitions[stage_name]
10
+ raise "#{stage_name} not found in Stage.definitions" if stage_definition.nil?
11
+ # requires
12
+ reqs = stage_definition.required_injections
13
+ if reqs
14
+ reqs.each do |req|
15
+ object = stage_context[req]
16
+ stage.define_singleton_method req do
17
+ components[req]
18
+ end
19
+ components = stage.send :components
20
+ components[req] = object
21
+ end
22
+ end
23
+
24
+ renderer_type = stage_definition.renderer || :renderer
25
+ renderer = stage_context[renderer_type]
26
+ stage_context[:renderer] = renderer unless renderer_type == :renderer
27
+ stage.define_singleton_method :renderer do
28
+ components[:renderer]
29
+ end
30
+ components = stage.send :components
31
+ components[:renderer] = renderer
32
+
33
+ # helpers
34
+ helpers = stage_definition.helpers_block
35
+ if helpers
36
+ helpers_module = Module.new &helpers
37
+ stage.extend helpers_module
38
+ end
39
+
40
+ stage.configure(backstage, opts)
41
+
42
+ # setup
43
+ stage.define_singleton_method(:curtain_up, &stage_definition.curtain_up_block) if stage_definition.curtain_up_block
44
+ stage.define_singleton_method(:curtain_down, &stage_definition.curtain_down_block) if stage_definition.curtain_down_block
45
+ end
46
+
47
+ rescue Exception => e
48
+ raise """
49
+ #{stage_name} not found:
50
+ #{e.inspect}
51
+ #{e.backtrace[0..6].join("\n")}
52
+ """
53
+ end
54
+ end
55
+ end
56
+ end