gamebox 0.0.6 → 0.0.7

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 (81) hide show
  1. data/History.txt +14 -0
  2. data/Manifest.txt +40 -37
  3. data/README.txt +2 -2
  4. data/Rakefile +27 -20
  5. data/TODO.txt +8 -8
  6. data/bin/gamebox +7 -1
  7. data/docs/getting_started.rdoc +2 -5
  8. data/docs/logo.png +0 -0
  9. data/lib/gamebox.rb +12 -1
  10. data/lib/gamebox/actor.rb +34 -9
  11. data/lib/gamebox/actor_factory.rb +25 -14
  12. data/lib/gamebox/actor_view.rb +6 -6
  13. data/lib/gamebox/{logo.rb → actors/logo.rb} +0 -0
  14. data/lib/gamebox/{score.rb → actors/score.rb} +2 -1
  15. data/lib/gamebox/{svg_actor.rb → actors/svg_actor.rb} +3 -4
  16. data/lib/gamebox/ai/polaris.rb +2 -0
  17. data/lib/gamebox/behavior.rb +3 -0
  18. data/lib/gamebox/{animated.rb → behaviors/animated.rb} +13 -5
  19. data/lib/gamebox/{graphical.rb → behaviors/graphical.rb} +11 -1
  20. data/lib/gamebox/{layered.rb → behaviors/layered.rb} +14 -0
  21. data/lib/gamebox/{physical.rb → behaviors/physical.rb} +41 -14
  22. data/lib/gamebox/{updatable.rb → behaviors/updatable.rb} +1 -1
  23. data/lib/gamebox/{templates/template_app → data}/config/objects.yml +4 -2
  24. data/lib/gamebox/data/graphics/logo.png +0 -0
  25. data/lib/gamebox/event_compat.rb +285 -0
  26. data/lib/gamebox/ftor.rb +2 -0
  27. data/lib/gamebox/gamebox_application.rb +12 -1
  28. data/lib/gamebox/generators/actor_generator.rb +2 -2
  29. data/lib/gamebox/generators/view_generator.rb +42 -0
  30. data/lib/gamebox/input_manager.rb +88 -21
  31. data/lib/gamebox/{aliasing.rb → lib/aliasing.rb} +0 -0
  32. data/lib/gamebox/{templates/template_app/lib → lib}/diy.rb +0 -0
  33. data/lib/gamebox/{inflections.rb → lib/inflections.rb} +0 -0
  34. data/lib/gamebox/{inflector.rb → lib/inflector.rb} +2 -2
  35. data/lib/gamebox/{linked_list.rb → lib/linked_list.rb} +0 -0
  36. data/lib/gamebox/{metaclass.rb → lib/metaclass.rb} +0 -0
  37. data/lib/gamebox/lib/numbers_ext.rb +3 -0
  38. data/lib/gamebox/{platform.rb → lib/platform.rb} +0 -0
  39. data/lib/gamebox/{publisher_ext.rb → lib/publisher_ext.rb} +0 -0
  40. data/lib/gamebox/{sorted_list.rb → lib/sorted_list.rb} +0 -0
  41. data/lib/gamebox/lib/surface_ext.rb +76 -0
  42. data/lib/gamebox/physical_director.rb +1 -1
  43. data/lib/gamebox/{physical_level.rb → physical_stage.rb} +28 -18
  44. data/lib/gamebox/physics.rb +2 -2
  45. data/lib/gamebox/resource_manager.rb +77 -8
  46. data/lib/gamebox/sound_manager.rb +15 -17
  47. data/lib/gamebox/stage.rb +143 -0
  48. data/lib/gamebox/stage_manager.rb +110 -0
  49. data/lib/gamebox/svg_document.rb +1 -1
  50. data/lib/gamebox/tasks/gamebox_tasks.rb +1 -1
  51. data/lib/gamebox/templates/{test_actor.erb → actor_spec.erb} +2 -2
  52. data/lib/gamebox/templates/actor_view.erb +8 -0
  53. data/lib/gamebox/templates/actor_view_spec.erb +10 -0
  54. data/lib/gamebox/templates/template_app/Rakefile +4 -4
  55. data/lib/gamebox/templates/template_app/config/game.yml +1 -0
  56. data/lib/gamebox/templates/template_app/config/stage_config.yml +2 -0
  57. data/lib/gamebox/templates/template_app/script/generate +2 -1
  58. data/lib/gamebox/templates/template_app/{test → spec}/helper.rb +0 -0
  59. data/lib/gamebox/templates/template_app/src/{demo_level.rb → demo_stage.rb} +5 -3
  60. data/lib/gamebox/templates/template_app/src/game.rb +4 -6
  61. data/lib/gamebox/version.rb +3 -2
  62. data/lib/gamebox/viewport.rb +18 -9
  63. data/lib/gamebox/{graphical_actor_view.rb → views/graphical_actor_view.rb} +13 -1
  64. data/lib/gamebox/wrapped_screen.rb +2 -1
  65. data/spec/actor_spec.rb +57 -0
  66. data/{test/test_animated.rb → spec/animated_spec.rb} +5 -6
  67. data/spec/helper.rb +24 -0
  68. data/{test/test_line_of_site.rb → spec/line_of_site_spec.rb} +1 -1
  69. data/{test/test_physical.rb → spec/physical_spec.rb} +3 -4
  70. data/{test/test_polaris.rb → spec/polaris_spec.rb} +1 -1
  71. data/{test/test_viewport.rb → spec/viewport_spec.rb} +11 -8
  72. metadata +53 -50
  73. data/docs/gamebox04_big.png +0 -0
  74. data/lib/gamebox/level.rb +0 -65
  75. data/lib/gamebox/mode.rb +0 -123
  76. data/lib/gamebox/mode_manager.rb +0 -80
  77. data/lib/gamebox/numbers_ext.rb +0 -3
  78. data/lib/gamebox/surface_ext.rb +0 -37
  79. data/lib/gamebox/templates/template_app/config/mode_level_config.yml +0 -3
  80. data/test/helper.rb +0 -26
  81. data/test/test_actor.rb +0 -36
@@ -0,0 +1,2 @@
1
+ require 'rubygame/ftor'
2
+ Ftor = Rubygame::Ftor
@@ -4,6 +4,8 @@ $: << "#{File.dirname(__FILE__)}/../config"
4
4
  require 'rubygems'
5
5
  require 'rubygame'
6
6
  include Rubygame
7
+ include Rubygame::Events
8
+ require 'event_compat'
7
9
  require 'surface_ext'
8
10
 
9
11
  require "environment"
@@ -23,7 +25,16 @@ class GameboxApp
23
25
  end
24
26
 
25
27
  def initialize
26
- @context = DIY::Context.from_file(APP_ROOT + '/config/objects.yml')
28
+ gamebox_objects = YAML.load(File.read(GAMEBOX_PATH + 'data/config/objects.yml'))
29
+
30
+ game_objects_file = APP_ROOT + '/config/objects.yml'
31
+ game_specific_objects = {}
32
+ if File.exist? game_objects_file
33
+ game_specific_objects = YAML.load(File.read(game_objects_file))
34
+ end
35
+ objects = gamebox_objects.merge! game_specific_objects
36
+
37
+ @context = DIY::Context.from_yaml(YAML.dump(objects))
27
38
  end
28
39
 
29
40
  def setup
@@ -28,13 +28,13 @@ class ActorGenerator
28
28
  end
29
29
 
30
30
  def build_test_actor
31
- template_file = File.open(File.join(GAMEBOX_PATH,'templates','test_actor.erb'))
31
+ template_file = File.open(File.join(GAMEBOX_PATH,'templates','actor_spec.erb'))
32
32
  template_contents = template_file.readlines.join
33
33
  actor_template = ERB.new(template_contents)
34
34
 
35
35
  result = actor_template.result @bind
36
36
 
37
- out_file = File.join(APP_ROOT,'test','test_'+Inflector.underscore(@actor_name)+".rb")
37
+ out_file = File.join(APP_ROOT,'spec',Inflector.underscore(@actor_name)+"_spec.rb")
38
38
  raise "File exists [#{out_file}]" if File.exists? out_file
39
39
  File.open(out_file,"w+") do |f|
40
40
  f.write result
@@ -0,0 +1,42 @@
1
+
2
+ class ViewGenerator
3
+ require 'erb'
4
+ def generate(*args)
5
+
6
+ @actor_view_name = ARGV[1]
7
+ @actor_view_name += "View" unless @actor_view_name.end_with? "View"
8
+ @behaviors = ARGV[2]
9
+ @bind = binding
10
+
11
+ build_actor_view
12
+ build_test_actor_view
13
+ end
14
+
15
+ def build_actor_view
16
+ template_file = File.open(File.join(GAMEBOX_PATH,'templates','actor_view.erb'))
17
+ template_contents = template_file.readlines.join
18
+ actor_view_template = ERB.new(template_contents)
19
+
20
+ result = actor_view_template.result @bind
21
+
22
+ out_file = File.join(APP_ROOT,'src',Inflector.underscore(@actor_view_name)+".rb")
23
+ raise "File exists [#{out_file}]" if File.exists? out_file
24
+ File.open(out_file,"w+") do |f|
25
+ f.write result
26
+ end
27
+ end
28
+
29
+ def build_test_actor_view
30
+ template_file = File.open(File.join(GAMEBOX_PATH,'templates','actor_view_spec.erb'))
31
+ template_contents = template_file.readlines.join
32
+ actor_view_template = ERB.new(template_contents)
33
+
34
+ result = actor_view_template.result @bind
35
+
36
+ out_file = File.join(APP_ROOT,'spec',Inflector.underscore(@actor_view_name)+"_spec.rb")
37
+ raise "File exists [#{out_file}]" if File.exists? out_file
38
+ File.open(out_file,"w+") do |f|
39
+ f.write result
40
+ end
41
+ end
42
+ end
@@ -1,26 +1,52 @@
1
1
  require 'publisher'
2
+
3
+ # InputManager handles the pumping of SDL for events and distributing of said events.
4
+ # You can gain access to these events by registering for all events,
5
+ # or just the ones you care about.
6
+ # All events:
7
+ # input_manager.when :event_received do |evt|
8
+ # ...
9
+ # end
10
+ #
11
+ # Some events:
12
+ # input_manager.reg KeyPressed, :space do
13
+ # ...
14
+ # end
15
+ #
16
+ # Don't forget to unreg for these things between stages,
17
+ # since the InputManager is shared across stages.
2
18
  class InputManager
3
19
  extend Publisher
4
20
  can_fire :key_up, :event_received
5
21
 
22
+
23
+ # lookup map for mouse button clicks
6
24
  MOUSE_BUTTON_LOOKUP = {
7
- 1 => :left,
8
- 2 => :middle,
9
- 3 => :right,
25
+ MOUSE_LEFT => :left,
26
+ MOUSE_MIDDLE => :middle,
27
+ MOUSE_RIGHT => :right,
10
28
  }
11
29
 
12
- attr_accessor :hooks
13
-
14
- def initialize
30
+ constructor :config_manager
31
+
32
+ # Sets up the clock and main event loop. You should never call this method,
33
+ # as this class should be initialized by diy.
34
+ def setup
15
35
  @queue = EventQueue.new
36
+ @queue.enable_new_style_events
16
37
  @queue.ignore = [
17
- ActiveEvent,
18
- JoyAxisEvent,
19
- JoyBallEvent,
20
- JoyDownEvent,
21
- JoyHatEvent,
22
- JoyUpEvent,
23
- ResizeEvent
38
+ InputFocusGained,
39
+ InputFocusLost,
40
+ MouseFocusGained,
41
+ MouseFocusLost,
42
+ WindowMinimized,
43
+ WindowUnminimized,
44
+ JoystickAxisMoved,
45
+ JoystickBallMoved,
46
+ JoystickButtonPressed,
47
+ JoystickButtonReleased,
48
+ JoystickHatMoved,
49
+ WindowResized
24
50
  ]
25
51
 
26
52
  @clock = Clock.new do |c|
@@ -31,39 +57,49 @@ class InputManager
31
57
  end
32
58
  end
33
59
 
60
+ @auto_quit = @config_manager[:auto_quit]
61
+
34
62
  @hooks = {}
35
63
  @non_id_hooks = {}
36
64
  end
37
65
 
66
+ # Sets the target framerate for the game.
67
+ # This setting controls how lock Clock#tick will delay.
38
68
  def framerate=(frame_rate)
39
69
  @clock.target_framerate = frame_rate
40
70
  end
41
71
 
72
+ # Returns the target framerate.
42
73
  def framerate
43
74
  @clock.target_framerate
44
75
  end
45
76
 
77
+ # This is where the queue gets pumped. This gets called from your game application.
46
78
  def main_loop(game)
47
79
  catch(:rubygame_quit) do
48
80
  loop do
49
81
  # add magic hooks
50
82
  @queue.each do |event|
51
83
  case event
52
- when KeyDownEvent
84
+ when KeyPressed
53
85
  case event.key
54
- when K_F
86
+ when :f
55
87
  puts "Framerate:#{@clock.framerate}"
56
- when K_ESCAPE
57
- throw :rubygame_quit
88
+ when @auto_quit
89
+ throw :rubygame_quit
58
90
  end
59
- when QuitEvent
91
+ when QuitRequested
60
92
  throw :rubygame_quit
61
93
  end
62
94
  fire :event_received, event
63
95
 
64
96
  event_hooks = @hooks[event.class]
65
97
  id = event.key if event.respond_to? :key
66
- id ||= MOUSE_BUTTON_LOOKUP[event.button] if event.respond_to? :button
98
+
99
+ if event.respond_to? :button
100
+ id ||= (MOUSE_BUTTON_LOOKUP[event.button] or event.button)
101
+ end
102
+
67
103
  unless id.nil?
68
104
  event_action_hooks = event_hooks[id] if event_hooks
69
105
  if event_action_hooks
@@ -86,7 +122,22 @@ class InputManager
86
122
  end
87
123
  end
88
124
 
125
+ # registers a block to be called when matching events are pulled from the SDL queue.
126
+ # ie
127
+ # input_manager.register_hook KeyPressed do |evt|
128
+ # # will be called on every key press
129
+ # end
130
+ # input_manager.register_hook KeyPressed, K_SPACE do |evt|
131
+ # # will be called on every spacebar key press
132
+ # end
89
133
  def register_hook(event_class, *event_ids, &block)
134
+ return unless block_given?
135
+ listener = eval("self", block.binding)
136
+ _register_hook listener, event_class, *event_ids, &block
137
+ end
138
+ alias reg register_hook
139
+
140
+ def _register_hook(listener, event_class, *event_ids, &block)
90
141
  return unless block_given?
91
142
  @hooks[event_class] ||= {}
92
143
  for event_id in event_ids
@@ -97,13 +148,15 @@ class InputManager
97
148
  if event_ids.empty?
98
149
  @non_id_hooks[event_class] << block
99
150
  end
100
- listener = eval("self", block.binding)
101
151
  listener.when :remove_me do
102
152
  unregister_hook event_class, *event_ids, &block
103
153
  end
104
154
  end
105
- alias reg register_hook
106
155
 
156
+ # unregisters a block to be called when matching events are pulled from the SDL queue.
157
+ # ie
158
+ # input_manager.unregister_hook KeyPressed, :space, registered_block
159
+ # also see InputManager#clear_hooks for clearing many hooks
107
160
  def unregister_hook(event_class, *event_ids, &block)
108
161
  @hooks[event_class] ||= {}
109
162
  for event_id in event_ids
@@ -117,6 +170,9 @@ class InputManager
117
170
  end
118
171
  alias unreg unregister_hook
119
172
 
173
+
174
+ # removes all blocks that are in the scope of listener's instance.
175
+ # clears all listeners if listener is nil
120
176
  def clear_hooks(listener=nil)
121
177
  if listener
122
178
  for event_klass, id_listeners in @hooks
@@ -137,4 +193,15 @@ class InputManager
137
193
  @non_id_hooks = {}
138
194
  end
139
195
  end
196
+
197
+ # autohook a boolean to be set to true while a key is pressed
198
+ def while_key_pressed(key, target, accessor)
199
+ _register_hook target, KeyPressed, key do
200
+ target.send accessor.to_s+"=", true
201
+ end
202
+ _register_hook target, KeyReleased, key do
203
+ target.send accessor.to_s+"=", false
204
+ end
205
+ end
206
+
140
207
  end
File without changes
File without changes
@@ -200,7 +200,7 @@ module Inflector
200
200
  class_name_in_module.to_s.gsub(/^.*::/, '')
201
201
  end
202
202
 
203
- # Create the name of a table like Rails does for models to table names. This method
203
+ # Create the name of a table like Rails does for stagels to table names. This method
204
204
  # uses the pluralize method on the last word in the string.
205
205
  #
206
206
  # Examples
@@ -211,7 +211,7 @@ module Inflector
211
211
  pluralize(underscore(class_name))
212
212
  end
213
213
 
214
- # Create a class name from a table name like Rails does for table names to models.
214
+ # Create a class name from a table name like Rails does for table names to stagels.
215
215
  # Note that this returns a string and not a Class. (To convert to an actual class
216
216
  # follow classify with constantize.)
217
217
  #
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ class Float
2
+ INFINITY = 1.0/0.0
3
+ end
File without changes
File without changes
@@ -0,0 +1,76 @@
1
+ require 'ftor'
2
+ include Rubygame::Color
3
+ module Rubygame
4
+ class Surface
5
+ def draw_line_s(point1, point2, color, thickness)
6
+ half_thickness = thickness/2.0
7
+ x1 = point1[0]
8
+ y1 = point1[1]
9
+ x2 = point2[0]
10
+ y2 = point2[1]
11
+
12
+ point1_vector = Ftor.new x1, y1
13
+ point2_vector = Ftor.new x2, y2
14
+
15
+ line_vector = point2_vector-point1_vector
16
+ perp_vector = line_vector.normal.unit
17
+
18
+ points = []
19
+ pvt = perp_vector*half_thickness
20
+ poly_point1 = Ftor.new(x1,y1)+pvt
21
+ poly_point2 = Ftor.new(x2,y2)+pvt
22
+ poly_point3 = Ftor.new(x2,y2)-pvt
23
+ poly_point4 = Ftor.new(x1,y1)-pvt
24
+
25
+ points << [poly_point1.x,poly_point1.y]
26
+ points << [poly_point2.x,poly_point2.y]
27
+ points << [poly_point3.x,poly_point3.y]
28
+ points << [poly_point4.x,poly_point4.y]
29
+ points << [poly_point1.x,poly_point1.y]
30
+
31
+ draw_polygon_s points, color
32
+ draw_circle_s [x1,y1], half_thickness, color
33
+ draw_circle_s [x2,y2], half_thickness, color
34
+ end
35
+
36
+ # BY IPPA
37
+ def fill_gradient(user_options = {})
38
+ # merge arguments from methodcall Over default options
39
+ default_options = {
40
+ :from_color => :black,
41
+ :to_color => :white,
42
+ :thickness => 10,
43
+ :orientation => :down,
44
+ :rect => Rect.new([0, 0, self.width, self.height])
45
+ }
46
+ options = default_options.merge(user_options)
47
+
48
+ # typecast color and rect arguments
49
+ from_color = (options[:from_color].is_a? ColorRGB)? options[:from_color] : Color[options[:from_color]]
50
+ to_color = (options[:to_color].is_a? ColorRGB)? options[:to_color] : Color[options[:to_color]]
51
+ rect = (options[:rect].is_a? Rect)? options[:rect] : Rect.new(:rect)
52
+
53
+ length = (options[:orientation] == :vertical) ? rect.height : rect.width
54
+ weight_step = 1.0 / (length.to_f / options[:thickness].to_f)
55
+ weight = 0.0
56
+ x = rect.x
57
+ y = rect.y
58
+
59
+ while weight < 1.0
60
+ color = to_color.average(from_color, weight)
61
+
62
+ if options[:orientation] == :vertical
63
+ self.draw_box_s([x, y], [rect.width, y + options[:thickness]], color)
64
+ y += options[:thickness]
65
+ else
66
+ self.draw_box_s([x, y],[x + options[:thickness], rect.height], color)
67
+ x += options[:thickness]
68
+ end
69
+
70
+ weight += weight_step
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ end # module Rubygame
@@ -12,6 +12,6 @@ class PhysicalDirector < Director
12
12
  end
13
13
 
14
14
  def actor_removed(act)
15
- act.level.unregister_physical_object act if act.is? :physical
15
+ act.stage.unregister_physical_object act if act.is? :physical
16
16
  end
17
17
  end
@@ -1,29 +1,26 @@
1
- # Levels represent on level of game play. Some games will likely have only one
2
- # level. Level is responsible for loading its background, props, and directors.
3
- # PhysicalLevel adds a physics space to the Level
4
- require 'level'
1
+ # Stage represent on level of game play. Some games will likely have only one
2
+ # stage. Stage is responsible for loading its background, props, and directors.
3
+ # PhysicalStage adds a physics space to the Stage
4
+ require 'stage'
5
5
  require 'physics'
6
6
  require 'physical_director'
7
- class PhysicalLevel < Level
7
+ class PhysicalStage < Stage
8
8
 
9
9
  attr_accessor :space
10
10
 
11
- def initialize(actor_factory, resource_manager, sound_manager, input_manager, viewport, opts={})
12
- @actor_factory = actor_factory
13
- @director = PhysicalDirector.new
14
- @actor_factory.director = @director
15
-
16
- @resource_manager = resource_manager
17
- @sound_manager = sound_manager
18
- @input_manager = input_manager
19
- @viewport = viewport
20
- @opts = opts
21
-
11
+ def setup
12
+ super
13
+ setup_space
14
+ end
15
+
16
+ def setup_space
22
17
  @space = Space.new
23
18
  @space.iterations = 20
24
- @space.elastic_iterations = 0
19
+ @space.elastic_iterations = 5
20
+ end
25
21
 
26
- setup
22
+ def create_director
23
+ PhysicalDirector.new
27
24
  end
28
25
 
29
26
  PHYSICS_STEP = 25.0
@@ -87,4 +84,17 @@ class PhysicalLevel < Level
87
84
  end
88
85
  end
89
86
 
87
+ # Find any / all objects who's bounding box currently contains
88
+ # the passed in screen position. Requires a block as this sets
89
+ # a callback all the way down in Chipmunk and could be called
90
+ # later in the future.
91
+ #
92
+ # This block is called on each actor found
93
+ def pick(x, y, &block)
94
+ @space.shape_point_query(vec2(x, y)) do |found|
95
+ actor = @director.find_physical_obj(found)
96
+ block.call(actor)
97
+ end
98
+ end
99
+
90
100
  end