gamebox 0.0.7 → 0.0.8
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/.gitignore +6 -0
- data/History.txt +6 -0
- data/Rakefile +25 -23
- data/TODO.txt +5 -3
- data/VERSION +1 -0
- data/bin/gamebox +2 -2
- data/docs/CODE_REVIEW +48 -0
- data/docs/getting_started.rdoc +30 -14
- data/gamebox.gemspec +184 -0
- data/lib/gamebox/actor.rb +29 -37
- data/lib/gamebox/actor_factory.rb +7 -24
- data/lib/gamebox/actors/curtain.rb +57 -0
- data/lib/gamebox/actors/label.rb +23 -0
- data/lib/gamebox/actors/score.rb +9 -5
- data/lib/gamebox/arbiter.rb +75 -0
- data/lib/gamebox/backstage.rb +17 -0
- data/lib/gamebox/behavior.rb +24 -1
- data/lib/gamebox/behaviors/animated.rb +2 -0
- data/lib/gamebox/behaviors/audible.rb +34 -0
- data/lib/gamebox/behaviors/collidable.rb +41 -0
- data/lib/gamebox/class_finder.rb +29 -0
- data/lib/gamebox/data/config/objects.yml +0 -1
- data/lib/gamebox/director.rb +13 -0
- data/lib/gamebox/gamebox_application.rb +2 -0
- data/lib/gamebox/input_manager.rb +58 -36
- data/lib/gamebox/{templates/template_app/lib → lib}/code_statistics.rb +0 -0
- data/lib/gamebox/lib/platform.rb +1 -0
- data/lib/gamebox/lib/surface_ext.rb +1 -1
- data/lib/gamebox/sound_manager.rb +11 -5
- data/lib/gamebox/spec/helper.rb +25 -0
- data/lib/gamebox/stage.rb +69 -2
- data/lib/gamebox/stage_manager.rb +6 -5
- data/lib/gamebox/tasks/gamebox_tasks.rb +18 -0
- data/lib/gamebox/templates/template_app/.gitignore +6 -0
- data/lib/gamebox/templates/template_app/README +3 -9
- data/lib/gamebox/templates/template_app/Rakefile +0 -13
- data/lib/gamebox/templates/template_app/spec/helper.rb +1 -1
- data/lib/gamebox/templates/template_app/src/demo_stage.rb +1 -1
- data/lib/gamebox/version.rb +1 -1
- data/lib/gamebox/views/graphical_actor_view.rb +13 -21
- data/spec/actor_spec.rb +12 -4
- data/spec/actor_view_spec.rb +16 -0
- data/spec/animated_spec.rb +1 -0
- data/spec/backstage_spec.rb +45 -0
- data/spec/behavior_spec.rb +11 -0
- data/spec/collidable_spec.rb +15 -0
- data/spec/label_spec.rb +11 -0
- data/spec/resource_manager_spec.rb +14 -0
- data/spec/stage_spec.rb +65 -0
- metadata +66 -34
- data/Manifest.txt +0 -97
- data/lib/gamebox/ftor.rb +0 -2
- data/lib/gamebox/templates/template_app/lib/platform.rb +0 -16
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'behavior'
|
2
|
+
|
3
|
+
class Collidable < Behavior
|
4
|
+
|
5
|
+
attr_accessor :shape, :radius, :width
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@shape = opts[:shape]
|
9
|
+
@radius = opts[:radius]
|
10
|
+
@width = opts[:width]
|
11
|
+
|
12
|
+
collidable_obj = self
|
13
|
+
|
14
|
+
@actor.instance_eval do
|
15
|
+
(class << self; self; end).class_eval do
|
16
|
+
define_method :shape do |*args|
|
17
|
+
collidable_obj.shape *args
|
18
|
+
end
|
19
|
+
define_method :radius do |*args|
|
20
|
+
collidable_obj.radius *args
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
register_actor
|
26
|
+
end
|
27
|
+
|
28
|
+
def register_actor
|
29
|
+
@actor.stage.register_collidable @actor
|
30
|
+
end
|
31
|
+
|
32
|
+
def bounding_box
|
33
|
+
[ @actor.x-@width,@actor.y-@width,
|
34
|
+
@actor.x+@width,@actor.y+@width ]
|
35
|
+
end
|
36
|
+
|
37
|
+
def bounding_circle
|
38
|
+
[ @actor.x+@radius, @actor.y+@radius, @radius]
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ClassFinder
|
2
|
+
|
3
|
+
# Name is an underscore name string or symbol
|
4
|
+
def find(name)
|
5
|
+
klass = nil
|
6
|
+
klass_name = Inflector.camelize(name)
|
7
|
+
|
8
|
+
begin
|
9
|
+
klass = Object.const_get(klass_name)
|
10
|
+
rescue NameError
|
11
|
+
# not there yet
|
12
|
+
begin
|
13
|
+
require "#{name}"
|
14
|
+
rescue LoadError => ex
|
15
|
+
# maybe its included somewhere else
|
16
|
+
ensure
|
17
|
+
begin
|
18
|
+
klass = Object.const_get(klass_name)
|
19
|
+
rescue
|
20
|
+
# leave this alone.. maybe there isnt a NameView
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
klass
|
26
|
+
end
|
27
|
+
module_function :find
|
28
|
+
|
29
|
+
end
|
data/lib/gamebox/director.rb
CHANGED
@@ -34,6 +34,19 @@ class Director
|
|
34
34
|
@actors.empty?
|
35
35
|
end
|
36
36
|
|
37
|
+
def pause
|
38
|
+
@paused_actors = @actors
|
39
|
+
@actors = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def unpause
|
43
|
+
unless @paused_actors.nil?
|
44
|
+
@actors.each{|actor| actor.remove_self }
|
45
|
+
@actors = @paused_actors
|
46
|
+
@paused_actors = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
37
50
|
def update(time)
|
38
51
|
for act in @dead_actors
|
39
52
|
@actors.delete act
|
@@ -80,46 +80,54 @@ class InputManager
|
|
80
80
|
loop do
|
81
81
|
# add magic hooks
|
82
82
|
@queue.each do |event|
|
83
|
-
|
84
|
-
|
85
|
-
case event.key
|
86
|
-
when :f
|
87
|
-
puts "Framerate:#{@clock.framerate}"
|
88
|
-
when @auto_quit
|
89
|
-
throw :rubygame_quit
|
90
|
-
end
|
91
|
-
when QuitRequested
|
92
|
-
throw :rubygame_quit
|
93
|
-
end
|
94
|
-
fire :event_received, event
|
83
|
+
_handle_event(event)
|
84
|
+
end
|
95
85
|
|
96
|
-
|
97
|
-
|
86
|
+
game.update @clock.tick
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
98
90
|
|
99
|
-
|
100
|
-
|
101
|
-
|
91
|
+
def _handle_event(event) #:nodoc:
|
92
|
+
case event
|
93
|
+
when KeyPressed
|
94
|
+
case event.key
|
95
|
+
when :f
|
96
|
+
puts "Framerate:#{@clock.framerate}"
|
97
|
+
when @auto_quit
|
98
|
+
throw :rubygame_quit
|
99
|
+
end
|
100
|
+
when QuitRequested
|
101
|
+
throw :rubygame_quit
|
102
|
+
end
|
103
|
+
fire :event_received, event
|
102
104
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
for callback in event_action_hooks
|
107
|
-
callback.call event
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
non_id_event_hooks = @non_id_hooks[event.class]
|
113
|
-
if non_id_event_hooks
|
114
|
-
for callback in non_id_event_hooks
|
115
|
-
callback.call event
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
105
|
+
# fix for pause bug?
|
106
|
+
@hooks ||= {}
|
107
|
+
@non_id_hooks ||= {}
|
119
108
|
|
120
|
-
|
109
|
+
event_hooks = @hooks[event.class]
|
110
|
+
id = event.key if event.respond_to? :key
|
111
|
+
|
112
|
+
if event.respond_to? :button
|
113
|
+
id ||= (MOUSE_BUTTON_LOOKUP[event.button] or event.button)
|
114
|
+
end
|
115
|
+
|
116
|
+
unless id.nil?
|
117
|
+
event_action_hooks = event_hooks[id] if event_hooks
|
118
|
+
if event_action_hooks
|
119
|
+
for callback in event_action_hooks
|
120
|
+
callback.call event
|
121
|
+
end
|
121
122
|
end
|
122
123
|
end
|
124
|
+
|
125
|
+
non_id_event_hooks = @non_id_hooks[event.class]
|
126
|
+
if non_id_event_hooks
|
127
|
+
for callback in non_id_event_hooks
|
128
|
+
callback.call event
|
129
|
+
end
|
130
|
+
end
|
123
131
|
end
|
124
132
|
|
125
133
|
# registers a block to be called when matching events are pulled from the SDL queue.
|
@@ -197,11 +205,25 @@ class InputManager
|
|
197
205
|
# autohook a boolean to be set to true while a key is pressed
|
198
206
|
def while_key_pressed(key, target, accessor)
|
199
207
|
_register_hook target, KeyPressed, key do
|
200
|
-
target.send accessor
|
208
|
+
target.send "#{accessor}=", true
|
201
209
|
end
|
202
210
|
_register_hook target, KeyReleased, key do
|
203
|
-
target.send accessor
|
211
|
+
target.send "#{accessor}=", false
|
204
212
|
end
|
205
213
|
end
|
206
214
|
|
215
|
+
def pause
|
216
|
+
@paused_hooks = @hooks
|
217
|
+
@paused_non_id_hooks = @non_id_hooks
|
218
|
+
@hooks = {}
|
219
|
+
@non_id_hooks = {}
|
220
|
+
end
|
221
|
+
|
222
|
+
def unpause
|
223
|
+
@hooks = @paused_hooks
|
224
|
+
@non_id_hooks = @paused_non_id_hooks
|
225
|
+
@paused_hooks = nil
|
226
|
+
@paused_non_id_hooks = nil
|
227
|
+
end
|
228
|
+
|
207
229
|
end
|
File without changes
|
data/lib/gamebox/lib/platform.rb
CHANGED
@@ -48,23 +48,26 @@ class SoundManager
|
|
48
48
|
|
49
49
|
# plays the sound based on the name with the specified volume level.
|
50
50
|
# play_sound :foo # play sound at 100% volume
|
51
|
-
def play_sound(what,
|
51
|
+
def play_sound(what, opts={})
|
52
52
|
if @enabled && @sounds[what]
|
53
|
+
volume = opts.delete :volume
|
53
54
|
@sound_thread = Thread.new do
|
54
55
|
@sounds[what].volume = volume if volume
|
55
|
-
@sounds[what].play
|
56
|
+
@sounds[what].play opts
|
56
57
|
end
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
61
|
# plays the music based on the name with the specified volume level.
|
61
62
|
# will loop until SoundManager#stop_music is called.
|
62
|
-
# play_music :foo, 0.8 # play music at 80% volumne
|
63
|
-
def play_music(what,
|
63
|
+
# play_music :foo, :volume => 0.8 # play music at 80% volumne
|
64
|
+
def play_music(what, opts={})
|
64
65
|
if @enabled && @music[what]
|
66
|
+
volume = opts.delete :volume
|
67
|
+
opts[:repeats] = -1 unless opts[:repeat]
|
65
68
|
@music_thread = Thread.new do
|
66
69
|
@music[what].volume = volume if volume
|
67
|
-
@music[what].play
|
70
|
+
@music[what].play opts
|
68
71
|
end
|
69
72
|
end
|
70
73
|
end
|
@@ -85,4 +88,7 @@ class SoundManager
|
|
85
88
|
end
|
86
89
|
end
|
87
90
|
|
91
|
+
# TODO
|
92
|
+
# def pause_all_sounds;end
|
93
|
+
|
88
94
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Helper methods and classes for writing specs for your gamebox application
|
2
|
+
module GameboxSpecHelpers
|
3
|
+
|
4
|
+
def create_actor(type, args = {})
|
5
|
+
InputManager.stub :setup
|
6
|
+
basic_opts = {
|
7
|
+
:stage => @stage = stub.as_null_object,
|
8
|
+
:input => @input_manager = InputManager.new(:config_manager => "config_manager"),
|
9
|
+
:sound => @sound_manager = stub.as_null_object,
|
10
|
+
:director => @director = stub.as_null_object,
|
11
|
+
:resources => @resource_manager = stub.as_null_object
|
12
|
+
}.merge(args)
|
13
|
+
|
14
|
+
klass = ClassFinder.find(type)
|
15
|
+
|
16
|
+
raise "Could not find actor class #{type}" unless klass
|
17
|
+
|
18
|
+
klass.new(basic_opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
Spec::Runner.configure do |configuration|
|
24
|
+
configuration.include GameboxSpecHelpers
|
25
|
+
end
|
data/lib/gamebox/stage.rb
CHANGED
@@ -2,16 +2,20 @@ require 'inflector'
|
|
2
2
|
require 'publisher'
|
3
3
|
require 'director'
|
4
4
|
require 'viewport'
|
5
|
+
require 'backstage'
|
6
|
+
require 'arbiter'
|
7
|
+
|
5
8
|
# Stage is a state that the game is in. (ie intro stage, multiplayer stage,
|
6
9
|
# single player stage).
|
7
10
|
class Stage
|
11
|
+
include Arbiter
|
8
12
|
extend Publisher
|
9
13
|
can_fire_anything
|
10
14
|
|
11
15
|
attr_accessor :drawables, :resource_manager, :sound_manager,
|
12
|
-
:director, :opts, :viewport, :input_manager
|
16
|
+
:director, :opts, :viewport, :input_manager, :backstage
|
13
17
|
|
14
|
-
def initialize(input_manager, actor_factory, resource_manager, sound_manager, config_manager, opts)
|
18
|
+
def initialize(input_manager, actor_factory, resource_manager, sound_manager, config_manager, backstage, opts)
|
15
19
|
@input_manager = input_manager
|
16
20
|
|
17
21
|
@resource_manager = resource_manager
|
@@ -24,6 +28,7 @@ class Stage
|
|
24
28
|
@actor_factory = actor_factory
|
25
29
|
@director = create_director
|
26
30
|
@actor_factory.director = @director
|
31
|
+
@backstage = backstage
|
27
32
|
|
28
33
|
@opts = opts
|
29
34
|
|
@@ -72,6 +77,8 @@ class Stage
|
|
72
77
|
def update(time)
|
73
78
|
@director.update time
|
74
79
|
@viewport.update time
|
80
|
+
find_collisions unless @collidable_actors.nil?
|
81
|
+
update_timers time
|
75
82
|
end
|
76
83
|
|
77
84
|
def curtain_raising(*args)
|
@@ -139,5 +146,65 @@ class Stage
|
|
139
146
|
prev_drawable_list
|
140
147
|
|
141
148
|
end
|
149
|
+
|
150
|
+
def remove_timer(name)
|
151
|
+
@timers ||= {}
|
152
|
+
@timers.delete name
|
153
|
+
end
|
154
|
+
|
155
|
+
def timer(name)
|
156
|
+
@timers ||= {}
|
157
|
+
@timers[name]
|
158
|
+
end
|
159
|
+
|
160
|
+
# add block to be executed every interval_ms millis
|
161
|
+
def add_timer(name, interval_ms, &block)
|
162
|
+
@timers ||= {}
|
163
|
+
@timers[name] = {:count => 0,
|
164
|
+
:interval_ms => interval_ms, :callback => block}
|
165
|
+
end
|
166
|
+
|
167
|
+
# update each timers counts, call any blocks that are over their interval
|
168
|
+
def update_timers(time_delta)
|
169
|
+
unless @timers.nil?
|
170
|
+
@timers.each do |name, timer_hash|
|
171
|
+
timer_hash[:count] += time_delta
|
172
|
+
if timer_hash[:count] > timer_hash[:interval_ms]
|
173
|
+
timer_hash[:count] -= timer_hash[:interval_ms]
|
174
|
+
timer_hash[:callback].call
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def on_pause(&block)
|
181
|
+
@pause_listeners ||= []
|
182
|
+
@pause_listeners << block if block_given?
|
183
|
+
end
|
184
|
+
|
185
|
+
def on_unpause(&block)
|
186
|
+
@unpause_listeners ||= []
|
187
|
+
@unpause_listeners << block if block_given?
|
188
|
+
end
|
189
|
+
|
190
|
+
def pause
|
191
|
+
@director.pause
|
192
|
+
@input_manager.pause
|
193
|
+
@paused_timers = @timers
|
194
|
+
@timers = nil
|
195
|
+
@pause_listeners.each do |listener|
|
196
|
+
listener.call
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def unpause
|
201
|
+
@director.unpause
|
202
|
+
@input_manager.unpause
|
203
|
+
@timers = @paused_timers
|
204
|
+
@paused_timers = nil
|
205
|
+
@unpause_listeners.each do |listener|
|
206
|
+
listener.call
|
207
|
+
end
|
208
|
+
end
|
142
209
|
end
|
143
210
|
|
@@ -7,6 +7,7 @@ class StageManager
|
|
7
7
|
|
8
8
|
def setup
|
9
9
|
@stages = {}
|
10
|
+
@backstage = Backstage.new
|
10
11
|
|
11
12
|
@actor_factory.stage_manager = self
|
12
13
|
stages = @resource_manager.load_config('stage_config')[:stages]
|
@@ -41,7 +42,7 @@ class StageManager
|
|
41
42
|
end
|
42
43
|
|
43
44
|
def create_stage(name, opts)
|
44
|
-
stage_instance = lookup_stage_class(name).new(@input_manager, @actor_factory, @resource_manager, @sound_manager, @config_manager, opts)
|
45
|
+
stage_instance = lookup_stage_class(name).new(@input_manager, @actor_factory, @resource_manager, @sound_manager, @config_manager, @backstage, opts)
|
45
46
|
|
46
47
|
stage_instance.when :next_stage do |*args|
|
47
48
|
next_stage *args
|
@@ -56,24 +57,24 @@ class StageManager
|
|
56
57
|
stage_instance
|
57
58
|
end
|
58
59
|
|
59
|
-
def next_stage
|
60
|
+
def next_stage(*args)
|
60
61
|
index = @stage_names.index @stage
|
61
62
|
if index == @stage_names.size-1
|
62
63
|
puts "last stage, exiting"
|
63
64
|
exit
|
64
65
|
end
|
65
66
|
@stages.delete @stage_names[index+1]
|
66
|
-
change_stage_to @stage_names[index+1]
|
67
|
+
change_stage_to @stage_names[index+1], *args
|
67
68
|
end
|
68
69
|
|
69
|
-
def prev_stage
|
70
|
+
def prev_stage(*args)
|
70
71
|
index = @stage_names.index @stage
|
71
72
|
if index == 0
|
72
73
|
puts "first stage, exiting"
|
73
74
|
exit
|
74
75
|
end
|
75
76
|
@stages.delete @stage_names[index-1]
|
76
|
-
change_stage_to @stage_names[index-1]
|
77
|
+
change_stage_to @stage_names[index-1], *args
|
77
78
|
end
|
78
79
|
|
79
80
|
def restart_stage(*args)
|