gamebox 0.4.0.rc5 → 0.4.0.rc11

Sign up to get free protection for your applications and to get access to all the features.
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