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
data/lib/gamebox/actor.rb
CHANGED
@@ -7,21 +7,20 @@ class Actor
|
|
7
7
|
can_fire_anything
|
8
8
|
|
9
9
|
attr_accessor :behaviors, :x, :y, :stage, :input_manager,
|
10
|
-
:resource_manager, :alive, :opts, :
|
11
|
-
:
|
12
|
-
|
10
|
+
:resource_manager, :alive, :opts, :visible, :director,
|
11
|
+
:actor_type
|
13
12
|
|
14
13
|
def initialize(opts={}) # :nodoc:
|
15
14
|
@opts = opts
|
16
|
-
@x =
|
17
|
-
@y =
|
15
|
+
@x = opts[:x]
|
16
|
+
@y = opts[:y]
|
18
17
|
@x ||= 0
|
19
18
|
@y ||= 0
|
20
19
|
@stage = opts[:stage]
|
21
20
|
@input_manager = opts[:input]
|
22
|
-
@sound_manager = opts[:sound]
|
23
21
|
@resource_manager = opts[:resources]
|
24
22
|
@director = opts[:director]
|
23
|
+
@actor_type = opts[:actor_type]
|
25
24
|
@alive = true
|
26
25
|
|
27
26
|
@behaviors = {}
|
@@ -109,18 +108,12 @@ class Actor
|
|
109
108
|
|
110
109
|
# Creates a new actor and returns it. (This actor will automatically be added to the Director.
|
111
110
|
def spawn(type, args={})
|
112
|
-
@stage.
|
113
|
-
end
|
114
|
-
|
115
|
-
# Plays a sound via the SoundManager. See SoundManager for
|
116
|
-
# details on how to "define" sounds.
|
117
|
-
def play_sound(*args)
|
118
|
-
@sound_manager.play_sound *args
|
111
|
+
@stage.spawn type, args
|
119
112
|
end
|
120
113
|
|
121
|
-
#
|
122
|
-
def
|
123
|
-
@
|
114
|
+
# Access to backstage for storage
|
115
|
+
def backstage
|
116
|
+
@stage.backstage
|
124
117
|
end
|
125
118
|
|
126
119
|
# to be defined in child class
|
@@ -142,29 +135,28 @@ class Actor
|
|
142
135
|
def visible?
|
143
136
|
@visible
|
144
137
|
end
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
@behaviors << h
|
159
|
-
end
|
160
|
-
else
|
161
|
-
@behaviors << a
|
138
|
+
|
139
|
+
def self.behaviors
|
140
|
+
@behaviors ||= []
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.has_behaviors(*args)
|
144
|
+
@behaviors ||= []
|
145
|
+
for a in args
|
146
|
+
if a.is_a? Hash
|
147
|
+
for k,v in a
|
148
|
+
h = {}
|
149
|
+
h[k]=v
|
150
|
+
@behaviors << h
|
162
151
|
end
|
152
|
+
else
|
153
|
+
@behaviors << a
|
163
154
|
end
|
164
|
-
@behaviors
|
165
|
-
end
|
166
|
-
define_method( :has_behavior ) do |*args|
|
167
|
-
has_behaviors *args
|
168
155
|
end
|
156
|
+
@behaviors
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.has_behavior(*args)
|
160
|
+
has_behaviors *args
|
169
161
|
end
|
170
162
|
end
|
@@ -2,10 +2,10 @@ require 'actor'
|
|
2
2
|
require 'graphical_actor_view'
|
3
3
|
|
4
4
|
# ActorFactory is responsible for loading all Actors. It passes along required params such as
|
5
|
-
# stage, input_manager,
|
5
|
+
# stage, input_manager, director, resource_manager. It also creates the ActorView
|
6
6
|
# associated with the Actor and registers it to the Stage be drawn.
|
7
7
|
class ActorFactory
|
8
|
-
constructor :input_manager
|
8
|
+
constructor :input_manager
|
9
9
|
|
10
10
|
attr_accessor :stage_manager, :director
|
11
11
|
|
@@ -15,27 +15,9 @@ class ActorFactory
|
|
15
15
|
cached_actor = @actor_cache[actor]
|
16
16
|
return cached_actor if cached_actor
|
17
17
|
|
18
|
+
model_klass = ClassFinder.find(actor)
|
19
|
+
view_klass = ClassFinder.find("#{actor}_view")
|
18
20
|
|
19
|
-
model_klass_name = Inflector.camelize actor
|
20
|
-
begin
|
21
|
-
model_klass = Object.const_get model_klass_name
|
22
|
-
rescue NameError
|
23
|
-
# not there yet
|
24
|
-
begin
|
25
|
-
require actor.to_s
|
26
|
-
require actor.to_s+"_view"
|
27
|
-
rescue LoadError => ex
|
28
|
-
# maybe its included somewhere else
|
29
|
-
ensure
|
30
|
-
model_klass = Object.const_get model_klass_name
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
begin
|
35
|
-
view_klass = Object.const_get model_klass_name+"View"
|
36
|
-
rescue Exception => ex
|
37
|
-
# hrm...
|
38
|
-
end
|
39
21
|
actor_def = {
|
40
22
|
:model_klass => model_klass,
|
41
23
|
:view_klass => view_klass
|
@@ -48,12 +30,13 @@ class ActorFactory
|
|
48
30
|
def build(actor, stage, opts={})
|
49
31
|
actor_def = cached_actor_def actor
|
50
32
|
|
33
|
+
actor_type = actor_def[:actor_type]
|
51
34
|
basic_opts = {
|
52
35
|
:stage => stage,
|
53
36
|
:input => @input_manager,
|
54
|
-
:sound => @sound_manager,
|
55
37
|
:director => @director,
|
56
|
-
:resources => stage.resource_manager
|
38
|
+
:resources => stage.resource_manager,
|
39
|
+
:actor_type => actor
|
57
40
|
}
|
58
41
|
merged_opts = basic_opts.merge(opts)
|
59
42
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'actor'
|
2
|
+
require 'publisher'
|
3
|
+
require 'actor_view'
|
4
|
+
|
5
|
+
class CurtainView < ActorView
|
6
|
+
def draw(target,x_off,y_off)
|
7
|
+
target.draw_box_s [0,0],[1024,800], [0,0,0,@actor.height]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Curtain < Actor
|
12
|
+
extend Publisher
|
13
|
+
|
14
|
+
can_fire :curtain_up, :curtain_down
|
15
|
+
|
16
|
+
has_behavior :updatable, :layered => {:layer => 99_999}
|
17
|
+
|
18
|
+
attr_accessor :height
|
19
|
+
|
20
|
+
FULL_CURTAIN = 255
|
21
|
+
NO_CURTAIN = 0
|
22
|
+
def setup
|
23
|
+
@duration_in_ms = @opts[:duration]
|
24
|
+
@duration_in_ms ||= 1000
|
25
|
+
|
26
|
+
case @opts[:dir]
|
27
|
+
when :up
|
28
|
+
@height = FULL_CURTAIN
|
29
|
+
@dir = -1
|
30
|
+
when :down
|
31
|
+
@height = NO_CURTAIN
|
32
|
+
@dir = 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Update curtain height 0-255 (alpha)
|
37
|
+
def update(time)
|
38
|
+
perc_change = time.to_f/@duration_in_ms
|
39
|
+
amount = FULL_CURTAIN * perc_change * @dir
|
40
|
+
@height += amount.floor
|
41
|
+
|
42
|
+
if @height < 0
|
43
|
+
@height = 0
|
44
|
+
if alive?
|
45
|
+
fire :curtain_up
|
46
|
+
remove_self
|
47
|
+
end
|
48
|
+
elsif @height > 255
|
49
|
+
@height = 255
|
50
|
+
if alive?
|
51
|
+
fire :curtain_down
|
52
|
+
remove_self
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class LabelView < ActorView
|
2
|
+
def draw(target,x_off,y_off)
|
3
|
+
actor.text_image.blit target.screen, [actor.x, actor.y]
|
4
|
+
end
|
5
|
+
end
|
6
|
+
class Label < Actor
|
7
|
+
attr_accessor :text, :text_image
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@text = @opts[:text]
|
11
|
+
@size = @opts[:size]
|
12
|
+
@font = @opts[:font]
|
13
|
+
@color = @opts[:color]
|
14
|
+
|
15
|
+
@text ||= ""
|
16
|
+
@size ||= 30
|
17
|
+
@font ||= "Asimov.ttf"
|
18
|
+
@color ||= [250,250,250,255]
|
19
|
+
|
20
|
+
font = resource_manager.load_font @font, @size
|
21
|
+
@text_image = font.render @text.to_s, true, @color
|
22
|
+
end
|
23
|
+
end
|
data/lib/gamebox/actors/score.rb
CHANGED
@@ -13,24 +13,28 @@ class ScoreView < ActorView
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
class Score < Actor
|
16
|
+
|
16
17
|
has_behavior :layered => {:layer => 999}
|
17
|
-
attr_accessor :score
|
18
18
|
|
19
19
|
def setup
|
20
|
-
clear
|
20
|
+
clear if backstage[:score].nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def score
|
24
|
+
backstage[:score]
|
21
25
|
end
|
22
26
|
|
23
27
|
def clear
|
24
|
-
|
28
|
+
backstage[:score] = 0
|
25
29
|
end
|
26
30
|
|
27
31
|
def +(amount)
|
28
|
-
|
32
|
+
backstage[:score] += amount
|
29
33
|
self
|
30
34
|
end
|
31
35
|
|
32
36
|
def -(amount)
|
33
|
-
|
37
|
+
backstage[:score] -= amount
|
34
38
|
self
|
35
39
|
end
|
36
40
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# this module gets mixed into a stage to allow it to handle collision detection
|
2
|
+
module Arbiter
|
3
|
+
|
4
|
+
def register_collidable(actor)
|
5
|
+
@collidable_actors ||= []
|
6
|
+
unless @collidable_actors.include? actor
|
7
|
+
actor.when :remove_me do
|
8
|
+
unregister_collidable actor
|
9
|
+
end
|
10
|
+
@collidable_actors << actor
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def unregister_collidable(actor)
|
15
|
+
@collidable_actors ||= []
|
16
|
+
@collidable_actors.delete actor
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_collision_of(first_objs, second_objs, &block)
|
20
|
+
first_objs = [first_objs].flatten
|
21
|
+
second_objs = [second_objs].flatten
|
22
|
+
|
23
|
+
@collision_handlers ||= {}
|
24
|
+
|
25
|
+
first_objs.each do |fobj|
|
26
|
+
second_objs.each do |sobj|
|
27
|
+
# puts "registering #{fobj} and #{sobj}"
|
28
|
+
@collision_handlers[fobj] ||= {}
|
29
|
+
@collision_handlers[fobj][sobj] = block
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO how is this going to get called?, method chaining update?
|
35
|
+
def find_collisions
|
36
|
+
collisions = []
|
37
|
+
@collidable_actors.size.times do |i|
|
38
|
+
first = @collidable_actors[i]
|
39
|
+
(@collidable_actors.size).times do |j|
|
40
|
+
second = @collidable_actors[i-j]
|
41
|
+
|
42
|
+
if collide?(first, second)
|
43
|
+
collisions << [first,second]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
collisions.each do |collision|
|
49
|
+
first = collision.first
|
50
|
+
second = collision.last
|
51
|
+
colliders = @collision_handlers[first.actor_type]
|
52
|
+
callback = colliders[second.actor_type] unless colliders.nil?
|
53
|
+
callback.call first, second unless callback.nil?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def collide?(object, other)
|
58
|
+
self.send "collide_#{object.shape}_#{object.shape}?", object, other
|
59
|
+
end
|
60
|
+
|
61
|
+
def collide_circle_circle?(object, other)
|
62
|
+
# puts "comparing #{object.actor_type}[#{object.object_id}] to #{other.actor_type}[#{other.object_id}]"
|
63
|
+
x = object.x + object.radius
|
64
|
+
y = object.y + object.radius
|
65
|
+
x_prime = other.x + other.radius
|
66
|
+
y_prime = other.y + other.radius
|
67
|
+
|
68
|
+
x_dist = (x_prime - x) * (x_prime - x)
|
69
|
+
y_dist = (y_prime - y) * (y_prime - y)
|
70
|
+
|
71
|
+
total_radius = object.radius + other.radius
|
72
|
+
x_dist + y_dist < (total_radius) * (total_radius)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Backstage is a place to store things across stages. It does not allow you to store Actors here.
|
2
|
+
class Backstage
|
3
|
+
def initialize
|
4
|
+
@storage = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def set(key, value)
|
8
|
+
raise "Actors cannot wander back stage!" if value.is_a? Actor
|
9
|
+
@storage[key] = value
|
10
|
+
end
|
11
|
+
alias []= set
|
12
|
+
|
13
|
+
def get(key)
|
14
|
+
@storage[key]
|
15
|
+
end
|
16
|
+
alias [] get
|
17
|
+
end
|
data/lib/gamebox/behavior.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
# Behavior is any type of behavior an actor can exibit.
|
2
2
|
class Behavior
|
3
|
-
attr_accessor :actor
|
3
|
+
attr_accessor :actor, :opts
|
4
4
|
|
5
5
|
def initialize(actor,opts={})
|
6
6
|
@actor = actor
|
7
7
|
@opts = opts
|
8
|
+
req_behs = self.class.required_behaviors
|
9
|
+
req_behs.each do |beh|
|
10
|
+
unless @actor.is? beh
|
11
|
+
@actor.is beh
|
12
|
+
end
|
13
|
+
end
|
8
14
|
setup
|
9
15
|
end
|
10
16
|
|
@@ -16,4 +22,21 @@ class Behavior
|
|
16
22
|
|
17
23
|
def update(time)
|
18
24
|
end
|
25
|
+
|
26
|
+
def self.required_behaviors
|
27
|
+
@required_behaviors ||= []
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.requires_behaviors(*args)
|
31
|
+
@required_behaviors ||= []
|
32
|
+
for a in args
|
33
|
+
@required_behaviors << a
|
34
|
+
end
|
35
|
+
@behaviors
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.requires_behavior(*args)
|
39
|
+
requires_behaviors(*args)
|
40
|
+
end
|
41
|
+
|
19
42
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'behavior'
|
2
|
+
|
3
|
+
class Audible < Behavior
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@sound_manager = @actor.stage.sound_manager
|
7
|
+
|
8
|
+
audible_obj = self
|
9
|
+
@actor.instance_eval do
|
10
|
+
(class << self; self; end).class_eval do
|
11
|
+
define_method :play_sound do |*args|
|
12
|
+
audible_obj.play_sound *args
|
13
|
+
end
|
14
|
+
define_method :stop_sound do |*args|
|
15
|
+
audible_obj.stop_sound *args
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
# Plays a sound via the SoundManager. See SoundManager for
|
24
|
+
# details on how to "define" sounds.
|
25
|
+
def play_sound(*args)
|
26
|
+
@sound_manager.play_sound *args
|
27
|
+
end
|
28
|
+
|
29
|
+
# Stops a sound via the SoundManager.
|
30
|
+
def stop_sound(*args)
|
31
|
+
@sound_manager.stop_sound *args
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|