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
@@ -0,0 +1,37 @@
1
+ module PostSetupHandlers
2
+
3
+ class FileWatcher
4
+
5
+ def self.setup(argv,env,config)
6
+ start_file_watcher if config[:debug] or argv.include?('--debug')
7
+ end
8
+
9
+ def self.filepaths
10
+ [ "src/behaviors/", "src/actors" ]
11
+ end
12
+
13
+ def self.start_file_watcher
14
+ log "File Watcher is now watching (#{filepaths.join(', ')}) for changes."
15
+
16
+ Thread.abort_on_exception = true
17
+
18
+ Thread.new do
19
+ require 'listen'
20
+ Listen.to(*filepaths, filter: /\.rb$/) do |modified, added, removed|
21
+ (modified + added).each do |path|
22
+ path[/([^\/]*)\.rb/]
23
+ filename = $1
24
+ case path
25
+ when /behaviors/
26
+ reload_behavior filename
27
+ when /actors/
28
+ load_actor filename
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,13 @@
1
+
2
+ module PostSetupHandlers
3
+
4
+ class GameboxAppAddDebugHelpers
5
+ def self.setup(argv,env,config)
6
+ if config[:debug] or ARGV.include?("--debug")
7
+ log "GameboxApp now includes DEBUG Helpers"
8
+ GameboxApp.send :include, DebugHelpers
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module PostSetupHandlers
2
+ class PryRemoteServer
3
+ def self.setup(argv,env,config)
4
+ start_remote_pry if config[:debug] or argv.include?('--debug')
5
+ end
6
+
7
+ def self.start_remote_pry
8
+ log "Pry Remote Server started!"
9
+
10
+ Thread.abort_on_exception = true
11
+
12
+ Thread.new do
13
+ loop do
14
+ begin
15
+ if th = DRb.thread
16
+ th.kill
17
+ end
18
+
19
+ binding.remote_pry
20
+ log "remote_pry returned"
21
+ rescue Exception => e
22
+ log "finished remote pry"
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -18,10 +18,114 @@ module GameboxSpecHelpers
18
18
  before { @_mocks_created = create_mocks(*mock_names_array) }
19
19
  subject { described_class.new @_mocks_created }
20
20
  end
21
+
22
+ def subjectify_behavior(behavior_name)
23
+ before {
24
+ @_beh_mock_names = Behavior.object_definition.component_names
25
+ @actor = evented_stub(mock("actor_for_#{behavior_name}"))
26
+ @_mocks_created = create_mocks *(@_beh_mock_names - [:actor])
27
+ @_mocks_created[:actor] = @actor
28
+
29
+
30
+ @behavior_definition = Behavior.definitions[behavior_name]
31
+ reqs = @behavior_definition.required_injections || []
32
+ reqs -= @_beh_mock_names
33
+ @_req_mocks = create_mocks(*reqs)
34
+ }
35
+ let (:opts) { {} }
36
+ subject {
37
+
38
+ # TODO so much duplication here from the *Factories
39
+ Behavior.new(@_mocks_created).tap do |behavior|
40
+ @_req_mocks.keys.each do |req|
41
+ object = @_req_mocks[req]
42
+ behavior.define_singleton_method req do
43
+ components[req]
44
+ end
45
+ components = behavior.send :components
46
+ components[req] = object
47
+ end
48
+
49
+ helpers = @behavior_definition.helpers_block
50
+ if helpers
51
+ helpers_module = Module.new &helpers
52
+ behavior.extend helpers_module
53
+ end
54
+
55
+ behavior.define_singleton_method :react_to, @behavior_definition.react_to_block if @behavior_definition.react_to_block
56
+
57
+ # TODO not sure the right way to mock this out
58
+ # deps = @behavior_definition.required_behaviors
59
+ # if deps
60
+ # deps.each do |beh|
61
+ # _add_behavior actor, beh unless actor.has_behavior?(beh)
62
+ # end
63
+ # end
64
+ behavior.configure(opts)
65
+ behavior.instance_eval &@behavior_definition.setup_block if @behavior_definition.setup_block
66
+ end
67
+ }
68
+ end
69
+
70
+ def subjectify_actor(actor_type)
71
+ actor_definition = Actor.definitions[actor_type]
72
+ before {
73
+ @_mocks_created = create_mocks *Actor.object_definition.component_names
74
+ }
75
+ subject {
76
+ Actor.new(@_mocks_created).tap do |actor|
77
+
78
+ actor_definition.behaviors.each do |behavior|
79
+ beh_opts = {}
80
+ beh_key = behavior
81
+
82
+ if behavior.is_a?(Hash)
83
+ beh_opts = behavior.values.first
84
+ beh_key = behavior.keys.first
85
+ end
86
+
87
+ actor_definition.attributes.each do |attr|
88
+ actor.has_attributes attr
89
+ end
90
+
91
+ actor.add_behavior beh_key, beh_opts
92
+ end
93
+ end
94
+ }
95
+ end
96
+
97
+ def subjectify_actor_view(view_name)
98
+ view_definition = ActorView.definitions[view_name]
99
+ before {
100
+ reqs = view_definition.required_injections || []
101
+
102
+ @_mocks_created = create_mocks( *ActorView.object_definition.component_names + reqs)
103
+ @_mocks_created[:actor] = evented_stub(@_mocks_created[:actor])
104
+
105
+ }
106
+ subject {
107
+ ActorView.new(@_mocks_created).tap do |view|
108
+ view.define_singleton_method :draw, &view_definition.draw_block if view_definition.draw_block
109
+ if view_definition.setup_block
110
+ view.define_singleton_method :setup, &view_definition.setup_block
111
+ view.configure
112
+ end
113
+ end
114
+ }
115
+ end
21
116
  end
22
117
 
23
118
  module InstanceMethods
24
119
 
120
+
121
+ def actor_stubs(actor, attributes={})
122
+ attributes.each do |att, value|
123
+ actor.stubs(att).returns(value)
124
+ actor.stubs(:do_or_do_not).with(att).returns(value)
125
+ end
126
+ end
127
+
128
+
25
129
  def create_actor(type=:actor, args={})
26
130
  act = create_conjected_object type, nil, false
27
131
  act.configure args.merge(actor_type: type)
@@ -130,21 +234,24 @@ module GameboxAcceptanceSpecHelpers
130
234
 
131
235
  def caption=(new_caption)
132
236
  end
237
+
238
+ def rotate(*args)
239
+ yield
240
+ end
133
241
  end
134
242
 
135
243
 
136
- class ::TestingStage < Stage
244
+ module ::TestStageHelpers
137
245
  attr_accessor :actors
138
-
139
- def initialize
140
- @actors = []
246
+ def actors
247
+ @actors ||= []
141
248
  end
142
249
 
143
250
  def create_actor(actor_type, *args)
144
251
  super.tap do |act|
145
- @actors << act
252
+ actors << act
146
253
  act.when :remove_me do
147
- @actors.delete act
254
+ actors.delete act
148
255
  end
149
256
  end
150
257
  end
@@ -155,6 +262,12 @@ module GameboxAcceptanceSpecHelpers
155
262
  end
156
263
  end
157
264
 
265
+ define_stage :testing do
266
+ helpers do
267
+ include TestStageHelpers
268
+ end
269
+ end
270
+
158
271
  module MockCalls
159
272
  attr_accessor :calls
160
273
  def method_missing(*args)
@@ -168,14 +281,13 @@ module GameboxAcceptanceSpecHelpers
168
281
 
169
282
  class ::MockImage
170
283
  include MockCalls
171
- attr_accessor :filename
172
- def initialize(filename)
284
+ attr_accessor :filename, :width, :height
285
+ def initialize(filename, w, h)
173
286
  _reset!
174
287
  @filename = filename
288
+ @width = w
289
+ @height = h
175
290
  end
176
-
177
- def width; 10; end
178
- def height; 20; end
179
291
  end
180
292
 
181
293
  class ::MockFont
@@ -200,7 +312,7 @@ module GameboxAcceptanceSpecHelpers
200
312
  public *Game.object_definition.component_names
201
313
 
202
314
  def configure
203
- stage_manager.change_stage_to :testing
315
+ stage_manager.change_stage_to stage_manager.default_stage
204
316
  end
205
317
 
206
318
  def stage(&blk)
@@ -211,6 +323,10 @@ module GameboxAcceptanceSpecHelpers
211
323
  stage_manager.current_stage
212
324
  end
213
325
 
326
+ def actors(actor_type)
327
+ stage_manager.current_stage.actors.select { |act| act.actor_type == actor_type }
328
+ end
329
+
214
330
  def actor(actor_type)
215
331
  stage_manager.current_stage.actors.detect { |act| act.actor_type == actor_type }
216
332
  end
@@ -220,10 +336,23 @@ module GameboxAcceptanceSpecHelpers
220
336
  end
221
337
 
222
338
  module InstanceMethods
223
- def mock_image(filename)
339
+ def mock_tiles(filename, width, height)
340
+ context = Conject.default_object_context
341
+ resource_manager = context[:resource_manager]
342
+
343
+ [].tap do |tiles|
344
+ (width * height).times do |i|
345
+ tiles << MockImage.new("#{filename}_#{i}", 16, 16)
346
+ end
347
+
348
+ resource_manager.stubs(:load_tiles).returns(tiles)
349
+ end
350
+ end
351
+
352
+ def mock_image(filename, w=10, h=20)
224
353
  context = Conject.default_object_context
225
354
  resource_manager = context[:resource_manager]
226
- MockImage.new(filename).tap do |img|
355
+ MockImage.new(filename, w, h).tap do |img|
227
356
  resource_manager.stubs(:load_image).with(filename).returns(img)
228
357
  end
229
358
  end
@@ -246,7 +375,17 @@ module GameboxAcceptanceSpecHelpers
246
375
  def see_text_drawn(text, opts)
247
376
  font = opts[:in]
248
377
  font.calls.should_not be_empty
249
- font.calls.first.first.should == :draw
378
+ first_call = font.calls.first
379
+
380
+ first_call[0].should == :draw
381
+ first_call[1].to_s.should == text
382
+ first_call[2].should == opts[:x] if opts[:x]
383
+ first_call[3].should == opts[:y] if opts[:y]
384
+ first_call[4].should == opts[:z] if opts[:z]
385
+ first_call[5].should == opts[:x_scale] if opts[:x_scale]
386
+ first_call[6].should == opts[:y_scale] if opts[:y_scale]
387
+ first_call[7].should == opts[:color] if opts[:color]
388
+
250
389
  font._reset!
251
390
  end
252
391
 
@@ -290,8 +429,15 @@ module GameboxAcceptanceSpecHelpers
290
429
  act.should have_no_attrs(attrs)
291
430
  end
292
431
 
293
- def update(time)
294
- gosu.update time
432
+ def update(time, opts={})
433
+ step = opts[:step] || time
434
+
435
+ num_updates = time / step
436
+ num_updates.times do
437
+ gosu.update step
438
+ end
439
+ left_over = time % step
440
+ gosu.update left_over unless left_over == 0
295
441
  end
296
442
 
297
443
  def draw
@@ -364,6 +510,8 @@ RSpec.configure do |configuration|
364
510
  config.fonts_path = "spec/fixtures/"
365
511
  config.music_path = "spec/fixtures/"
366
512
  config.sound_path = "spec/fixtures/"
513
+ config.game_name = "Some Title!"
514
+ config.needs_cursor = true
367
515
  config.stages = [:testing]
368
516
  end
369
517
 
@@ -1,9 +1,10 @@
1
1
  require 'gamebox/lib/platform'
2
+ require "erb"
2
3
 
3
4
  desc "Run the game"
4
5
  task :run do |t|
5
- sh "bundle exec ruby src/app.rb"
6
- end
6
+ sh "bundle exec ruby #{APP_ROOT}src/app.rb"
7
+ end
7
8
  task :default => :run
8
9
 
9
10
  desc "Report code statistics (KLOCs, etc) from the application"
@@ -15,7 +16,7 @@ end
15
16
 
16
17
  desc "Run the game with debug server"
17
18
  task :debug do |t|
18
- sh "ruby src/app.rb -debug-server"
19
+ sh "bundle exec ruby #{APP_ROOT}src/app.rb -debug-server"
19
20
  end
20
21
 
21
22
  desc "Bundle in all required gems"
@@ -40,6 +41,21 @@ task :spec do
40
41
  end
41
42
  end
42
43
 
44
+ namespace :generate do
45
+ #didnt't use pluralize in here because I didnt want to include all of active support just for pluralize
46
+ [:actor, :stage, :behavior].each do |generator_name|
47
+ desc "generate a new #{generator_name} in the #{ generator_name }s folder"
48
+ task generator_name, "#{generator_name}_name".to_sym do |t, args|
49
+ File.open(File.join(File.dirname(__FILE__), "../../..", "/templates/#{generator_name}_template.erb")) do |io|
50
+ template = ERB.new io.read
51
+ instance_variable_set("@#{generator_name}_name", args["#{generator_name}_name"])
52
+ File.open "#{APP_ROOT}src/#{ generator_name}s/#{args["#{generator_name}_name"]}_#{generator_name}.rb", "w" do |out|
53
+ out.puts template.result binding
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
43
59
 
44
60
  namespace :dist do
45
61
  desc "Build a .app for your gamebox game"
@@ -47,7 +63,7 @@ namespace :dist do
47
63
  GAME_NAME = "UntitledGame" unless defined?(GAME_NAME)
48
64
  # DL template os x app
49
65
  remote_file = "gosu-mac-wrapper-#{Gosu::VERSION}.tar.gz"
50
- mac_build = "build/mac"
66
+ mac_build = "#{APP_ROOT}build/mac"
51
67
  local_file = "#{mac_build}/#{remote_file}"
52
68
 
53
69
  require 'net/http'
@@ -55,12 +71,11 @@ namespace :dist do
55
71
  # if false
56
72
  Net::HTTP.start("www.libgosu.org") do |http|
57
73
  resp = http.get("/downloads/#{remote_file}")
58
- open(local_file, "wb") { |file| file.write(resp.body) }
74
+ open(local_file, "wb") { |file| file.write(resp.body) }
59
75
  end
60
76
  # end
61
77
 
62
78
  # Expand it
63
- root = pwd
64
79
  cd mac_build
65
80
  `tar xzf #{remote_file}`
66
81
  app_name = "#{GAME_NAME}.app"
@@ -78,10 +93,10 @@ namespace :dist do
78
93
  clean_em_out = %w(chingu chingu.rb).map{|it| "#{dot_app_lib}/#{it}"}
79
94
  rm_rf clean_em_out#, :verbose => true, :noop => true
80
95
 
81
- cd root
96
+ cd APP_ROOT
82
97
  p `bundle --system package`
83
98
  p `bundle package`
84
- p `bundle --deployment`
99
+ p `bundle --deployment`
85
100
  mkdir_p gem_vendored
86
101
  rejects = %w(chipmunk gosu)
87
102
  Dir["vendor/bundle/ruby/**/gems/**/lib"].each do |gemmy|
@@ -98,7 +113,7 @@ namespace :dist do
98
113
  rejects = %w(spec src/app.rb vendor Main.rb)
99
114
  ok_dirs = %w(config gems src)
100
115
  REQUIRE_ALLS = ok_dirs.map{|dir| Dir.glob("\#{dir}/*.rb").reject{ |f| rejects.any?{|exclude| f.match exclude}}}.flatten
101
-
116
+
102
117
  require 'environment'
103
118
 
104
119
  GameboxApp.run ARGV, ENV
@@ -113,13 +128,13 @@ namespace :dist do
113
128
  f.puts plist.gsub "UntitledGame", GAME_NAME
114
129
  end
115
130
  end
116
-
131
+
117
132
  task :win do
118
133
  # create dist dir
119
- FileUtils.mkdir "dist" unless File.exist? "dist"
134
+ FileUtils.mkdir "#{APP_ROOT}dist" unless File.exist? "dist"
120
135
  # pull down windows app shell
121
136
  # expand into place
122
- sh 'cd dist; wget http://github.com/downloads/shawn42/gamebox/gamebox_app.zip; unzip gamebox_app.zip; mv gamebox_app/* .; rm gamebox_app.zip; rm -rf gamebox_app'
137
+ sh 'cd #{APP_ROOT}dist; wget http://github.com/downloads/shawn42/gamebox/gamebox_app.zip; unzip gamebox_app.zip; mv gamebox_app/* .; rm gamebox_app.zip; rm -rf gamebox_app'
123
138
 
124
139
  # copy config/src/lib/data into dist/src
125
140
  %w{vendor config data }.each do |dir|