gamebox 0.2.1 → 0.3.2
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/Gemfile +1 -8
- data/Rakefile +13 -37
- data/TODO.txt +27 -27
- data/docs/getting_started.rdoc +2 -2
- data/gamebox.gemspec +33 -191
- data/lib/gamebox.rb +18 -14
- data/lib/gamebox/actor.rb +37 -27
- data/lib/gamebox/actor_factory.rb +4 -5
- data/lib/gamebox/actor_view.rb +8 -0
- data/lib/gamebox/actors/collidable_debugger.rb +2 -2
- data/lib/gamebox/actors/curtain.rb +3 -3
- data/lib/gamebox/actors/emitter.rb +51 -0
- data/lib/gamebox/actors/label.rb +27 -7
- data/lib/gamebox/actors/logo.rb +1 -1
- data/lib/gamebox/actors/spatial_debugger.rb +25 -10
- data/lib/gamebox/arbiter.rb +61 -34
- data/lib/gamebox/behavior.rb +3 -3
- data/lib/gamebox/behaviors/animated.rb +1 -1
- data/lib/gamebox/behaviors/audible.rb +1 -1
- data/lib/gamebox/behaviors/collidable.rb +9 -4
- data/lib/gamebox/behaviors/collidable/aabb_collidable.rb +26 -1
- data/lib/gamebox/behaviors/collidable/circle_collidable.rb +3 -3
- data/lib/gamebox/behaviors/collidable/polygon_collidable.rb +1 -1
- data/lib/gamebox/behaviors/graphical.rb +30 -4
- data/lib/gamebox/behaviors/layered.rb +1 -1
- data/lib/gamebox/behaviors/physical.rb +113 -30
- data/lib/gamebox/behaviors/timed.rb +33 -0
- data/lib/gamebox/behaviors/updatable.rb +1 -1
- data/lib/gamebox/class_finder.rb +1 -21
- data/lib/gamebox/console_app.rb +33 -31
- data/lib/gamebox/constants.rb +481 -0
- data/lib/gamebox/data/config/objects.yml +7 -0
- data/lib/gamebox/gamebox_application.rb +10 -33
- data/lib/gamebox/gamebox_generator.rb +32 -32
- data/lib/gamebox/input_manager.rb +73 -32
- data/lib/gamebox/lib/inflector.rb +1 -1
- data/lib/gamebox/lib/range_ext.rb +5 -0
- data/lib/gamebox/lib/rect.rb +548 -548
- data/lib/gamebox/lib/sorted_list.rb +1 -1
- data/lib/gamebox/lib/symbol_ext.rb +8 -0
- data/lib/gamebox/physical_director.rb +1 -1
- data/lib/gamebox/physical_stage.rb +3 -3
- data/lib/gamebox/physics.rb +0 -3
- data/lib/gamebox/resource_manager.rb +22 -17
- data/lib/gamebox/sound_manager.rb +3 -2
- data/lib/gamebox/spatial_hash.rb +60 -31
- data/lib/gamebox/spatial_stagehand.rb +30 -6
- data/lib/gamebox/spec/helper.rb +7 -7
- data/lib/gamebox/stage.rb +18 -19
- data/lib/gamebox/stage_manager.rb +33 -23
- data/lib/gamebox/stagehand.rb +3 -0
- data/lib/gamebox/svg_document.rb +1 -1
- data/lib/gamebox/tasks/gamebox_tasks.rake +133 -0
- data/lib/gamebox/templates/actor.erb +0 -2
- data/lib/gamebox/templates/actor_view.erb +1 -3
- data/lib/gamebox/templates/template_app/Gemfile +3 -2
- data/lib/gamebox/templates/template_app/Rakefile +3 -8
- data/lib/gamebox/templates/template_app/config/environment.rb +7 -39
- data/lib/gamebox/templates/template_app/src/demo_stage.rb +1 -2
- data/lib/gamebox/templates/template_app/src/my_actor.rb +0 -3
- data/lib/gamebox/version.rb +2 -2
- data/lib/gamebox/viewport.rb +44 -8
- data/lib/gamebox/views/graphical_actor_view.rb +22 -16
- data/lib/gamebox/wrapped_screen.rb +9 -1
- data/script/perf_spatial_hash.rb +49 -58
- data/script/perf_struct_vs_array.rb +32 -0
- data/spec/actor_factory_spec.rb +61 -0
- data/spec/actor_spec.rb +24 -18
- data/spec/actor_view_spec.rb +51 -6
- data/spec/animated_spec.rb +27 -6
- data/spec/arbiter_spec.rb +12 -24
- data/spec/backstage_spec.rb +1 -1
- data/spec/behavior_spec.rb +3 -3
- data/spec/class_finder_spec.rb +13 -0
- data/spec/collidable_spec.rb +30 -10
- data/spec/emitter_spec.rb +20 -0
- data/spec/helper.rb +5 -21
- data/spec/input_manager_spec.rb +134 -0
- data/spec/label_spec.rb +0 -1
- data/spec/physical_spec.rb +114 -5
- data/spec/resource_manager_spec.rb +1 -2
- data/spec/spatial_hash_spec.rb +23 -7
- data/spec/spatial_stagehand_spec.rb +97 -0
- data/spec/stage_manager_spec.rb +0 -1
- data/spec/stage_spec.rb +2 -2
- data/spec/viewport_spec.rb +92 -48
- metadata +223 -119
- data/.gitignore +0 -11
- data/History.txt +0 -80
- data/VERSION +0 -1
- data/lib/gamebox/event_compat.rb +0 -285
- data/lib/gamebox/lib/diy.rb +0 -371
- data/lib/gamebox/lib/numbers_ext.rb +0 -3
- data/lib/gamebox/tasks/gamebox_tasks.rb +0 -61
- data/load_paths.rb +0 -20
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'actor'
|
2
|
-
require 'graphical_actor_view'
|
3
1
|
|
4
2
|
# ActorFactory is responsible for loading all Actors. It passes along required params such as
|
5
3
|
# stage, input_manager, director, resource_manager. It also creates the ActorView
|
@@ -16,6 +14,8 @@ class ActorFactory
|
|
16
14
|
return cached_actor if cached_actor
|
17
15
|
|
18
16
|
model_klass = ClassFinder.find(actor)
|
17
|
+
raise "#{actor} not found" unless model_klass
|
18
|
+
|
19
19
|
view_klass = ClassFinder.find("#{actor}_view")
|
20
20
|
|
21
21
|
actor_def = {
|
@@ -30,16 +30,15 @@ class ActorFactory
|
|
30
30
|
def build(actor, stage, opts={})
|
31
31
|
actor_def = cached_actor_def actor
|
32
32
|
|
33
|
-
actor_type = actor_def[:actor_type]
|
34
33
|
basic_opts = {
|
35
34
|
:stage => stage,
|
36
35
|
:input => @input_manager,
|
37
36
|
:director => @director,
|
38
37
|
:resources => stage.resource_manager,
|
39
|
-
:actor_type => actor
|
38
|
+
:actor_type => actor,
|
39
|
+
:wrapped_screen => @wrapped_screen
|
40
40
|
}
|
41
41
|
merged_opts = basic_opts.merge(opts)
|
42
|
-
|
43
42
|
model = actor_def[:model_klass].new merged_opts
|
44
43
|
|
45
44
|
view_klass = opts[:view]
|
data/lib/gamebox/actor_view.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
# class used for particle emissions
|
2
|
+
class Emitter < Actor
|
3
|
+
|
4
|
+
# options:
|
5
|
+
# delay: ms to wait between creating more particles
|
6
|
+
# particle_actor: actor to spawn as particle
|
7
|
+
# particle_opts: opts to be passed to the spawned particle
|
8
|
+
# ttl: ms to live (optional, will live forever if omitted)
|
9
|
+
# spawn_variance: dist in pixels to spawn away from emitter (default -10..10)
|
10
|
+
# location_tween: tween object that will be used to move the emitter (optional)
|
11
|
+
# follow: actor to follow (optional)
|
12
|
+
def setup
|
13
|
+
@variance = opts[:spawn_variance] || (-10..10)
|
14
|
+
|
15
|
+
spawn_timer = "#{self.object_id}_spawn"
|
16
|
+
self.when :remove_me do
|
17
|
+
stage.remove_timer spawn_timer
|
18
|
+
end
|
19
|
+
stage.add_timer spawn_timer, opts[:delay] do
|
20
|
+
spawn_particle
|
21
|
+
end
|
22
|
+
ttl = opts[:ttl]
|
23
|
+
if ttl
|
24
|
+
suicide_timer = "#{self.object_id}_ttl"
|
25
|
+
stage.add_timer suicide_timer, ttl do
|
26
|
+
stage.remove_timer suicide_timer
|
27
|
+
remove_self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
target = opts[:follow]
|
32
|
+
if target
|
33
|
+
self.x = target.x
|
34
|
+
self.y = target.y
|
35
|
+
target.when :x_changed do
|
36
|
+
self.x = target.x
|
37
|
+
end
|
38
|
+
target.when :y_changed do
|
39
|
+
self.y = target.y
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def spawn_particle
|
46
|
+
spawn_x = self.x + @variance.sample
|
47
|
+
spawn_y = self.y + @variance.sample
|
48
|
+
|
49
|
+
spawn opts[:particle_actor], {x: spawn_x, y: spawn_y}.merge(opts[:particle_opts])
|
50
|
+
end
|
51
|
+
end
|
data/lib/gamebox/actors/label.rb
CHANGED
@@ -1,23 +1,43 @@
|
|
1
1
|
class LabelView < ActorView
|
2
|
-
def draw(target,x_off,y_off)
|
3
|
-
|
2
|
+
def draw(target,x_off,y_off,z)
|
3
|
+
@converted_color ||= target.convert_color(actor.color)
|
4
|
+
actor.font.draw actor.text, actor.x, actor.y, z,
|
5
|
+
1,1, # x factor, y factor
|
6
|
+
@converted_color
|
4
7
|
end
|
5
8
|
end
|
9
|
+
|
6
10
|
class Label < Actor
|
7
|
-
|
11
|
+
has_behavior layered: {layer: 1}
|
12
|
+
attr_accessor :text, :font, :color
|
8
13
|
|
9
14
|
def setup
|
10
15
|
@text = @opts[:text]
|
11
16
|
@size = @opts[:size]
|
12
|
-
|
17
|
+
font_name = @opts[:font]
|
13
18
|
@color = @opts[:color]
|
14
19
|
|
15
20
|
@text ||= ""
|
16
21
|
@size ||= 30
|
17
|
-
|
22
|
+
font_name ||= "Asimov.ttf"
|
18
23
|
@color ||= [250,250,250,255]
|
24
|
+
layer = opts[:layer]
|
25
|
+
layered.layer = layer
|
26
|
+
|
27
|
+
@font = resource_manager.load_font font_name, @size
|
28
|
+
end
|
29
|
+
|
30
|
+
def width
|
31
|
+
font.text_width(text)
|
32
|
+
end
|
33
|
+
|
34
|
+
def height
|
35
|
+
[font.text_width(text),font.height]
|
36
|
+
end
|
19
37
|
|
20
|
-
|
21
|
-
@
|
38
|
+
def resize(size)
|
39
|
+
@size = size
|
40
|
+
resource_manager.load_font @font, @size
|
22
41
|
end
|
42
|
+
|
23
43
|
end
|
data/lib/gamebox/actors/logo.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
|
2
|
+
|
3
3
|
|
4
4
|
class SpatialDebugger < Actor
|
5
5
|
|
@@ -24,24 +24,39 @@ end
|
|
24
24
|
|
25
25
|
class SpatialDebuggerView < ActorView
|
26
26
|
def setup
|
27
|
-
size = 30
|
28
|
-
font = "Asimov.ttf"
|
29
|
-
@font = @actor.resource_manager.load_font font, size
|
27
|
+
# size = 30
|
28
|
+
# font = "Asimov.ttf"
|
29
|
+
# @font = @actor.resource_manager.load_font font, size
|
30
30
|
end
|
31
31
|
|
32
|
-
def draw(target,x_off,y_off)
|
32
|
+
def draw(target,x_off,y_off, z)
|
33
|
+
vp = stage.viewport
|
33
34
|
cell_size = @actor.spatial.cell_size
|
34
35
|
max = 0
|
35
36
|
@actor.spatial.buckets.each do |x_bucket,stuff|
|
36
37
|
stuff.each do |y_bucket,items|
|
37
|
-
max = items.size if items.size > max
|
38
|
+
# max = items.size if items.size > max
|
38
39
|
x = x_bucket * cell_size + x_off
|
39
40
|
y = y_bucket * cell_size + y_off
|
40
|
-
target.draw_box
|
41
|
+
target.draw_box x, y, x+cell_size, y+cell_size, [255,25,25], z
|
42
|
+
|
43
|
+
# Yes I know I may be drawing this many times for an actor
|
44
|
+
items.each do |item|
|
45
|
+
# puts "#{item.class}: [#{item.center_x}, #{item.center_y}] #{item.collidable_shape}"
|
46
|
+
parallax = 1
|
47
|
+
ix = item.center_x + x_off
|
48
|
+
iy = item.center_y + y_off
|
49
|
+
|
50
|
+
target.draw_box ix, iy, ix + 2, iy + 2, [255,255,255], 10
|
51
|
+
|
52
|
+
# TODO make work for non circles
|
53
|
+
r = item.radius
|
54
|
+
target.draw_box ix-r, iy-r, ix + r, iy + r, [255,255,255], 10
|
55
|
+
end
|
41
56
|
end
|
42
57
|
end
|
43
58
|
|
44
|
-
@text_image = @font.render "#{@actor.ratio} [#{max}]", true, Color[:white]
|
45
|
-
@text_image.blit target.screen, [@actor.x, @actor.y]
|
59
|
+
# @text_image = @font.render "#{@actor.ratio} [#{max}]", true, Color[:white]
|
60
|
+
# @text_image.blit target.screen, [@actor.x, @actor.y]
|
46
61
|
end
|
47
62
|
end
|
data/lib/gamebox/arbiter.rb
CHANGED
@@ -3,21 +3,11 @@ module Arbiter
|
|
3
3
|
attr_reader :checks, :collisions
|
4
4
|
|
5
5
|
def register_collidable(actor)
|
6
|
-
|
7
|
-
@collidable_actors ||= []
|
8
|
-
unless @collidable_actors.include? actor
|
9
|
-
actor.when :remove_me do
|
10
|
-
unregister_collidable actor
|
11
|
-
end
|
12
|
-
@collidable_actors << actor
|
13
|
-
@spatial_hash.add(actor)
|
14
|
-
end
|
6
|
+
stagehand(:spatial).add(actor)
|
15
7
|
end
|
16
8
|
|
17
9
|
def unregister_collidable(actor)
|
18
|
-
|
19
|
-
@collidable_actors.delete actor
|
20
|
-
@spatial_hash.remove(actor)
|
10
|
+
stagehand(:spatial).remove(actor)
|
21
11
|
end
|
22
12
|
|
23
13
|
def on_collision_of(first_objs, second_objs, &block)
|
@@ -28,7 +18,7 @@ module Arbiter
|
|
28
18
|
|
29
19
|
first_objs.each do |fobj|
|
30
20
|
second_objs.each do |sobj|
|
31
|
-
if fobj
|
21
|
+
if fobj < sobj
|
32
22
|
@collision_handlers[fobj] ||= {}
|
33
23
|
@collision_handlers[fobj][sobj] = [false,block]
|
34
24
|
else
|
@@ -44,7 +34,7 @@ module Arbiter
|
|
44
34
|
collisions.each do |collision|
|
45
35
|
first = collision.first
|
46
36
|
second = collision.last
|
47
|
-
unless first.actor_type
|
37
|
+
unless first.actor_type < second.actor_type
|
48
38
|
tmp = first
|
49
39
|
first = second
|
50
40
|
second = tmp
|
@@ -63,29 +53,33 @@ module Arbiter
|
|
63
53
|
end
|
64
54
|
|
65
55
|
def find_collisions
|
66
|
-
|
56
|
+
spatial_hash = stagehand(:spatial)
|
57
|
+
collidable_actors = spatial_hash.moved_items
|
67
58
|
@checks = 0
|
68
59
|
@collisions = 0
|
69
|
-
tmp_collidable_actors = @collidable_actors.dup
|
70
60
|
collisions = {}
|
71
61
|
|
72
|
-
|
73
|
-
x = first.x -
|
74
|
-
y = first.y -
|
62
|
+
collidable_actors.each do |first|
|
63
|
+
x = first.x - spatial_hash.cell_size
|
64
|
+
y = first.y - spatial_hash.cell_size
|
75
65
|
# TODO base this on size of object
|
76
|
-
w =
|
66
|
+
w = spatial_hash.cell_size * 3
|
77
67
|
h = w
|
78
68
|
|
79
|
-
tmp_collidable_actors =
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
69
|
+
tmp_collidable_actors = spatial_hash.neighbors_of(first)
|
70
|
+
|
71
|
+
if first.is? :collidable
|
72
|
+
tmp_collidable_actors.each do |second|
|
73
|
+
@checks += 1
|
74
|
+
if second.is? :collidable
|
75
|
+
if first != second && collide?(first, second)
|
76
|
+
collisions[second] ||= []
|
77
|
+
if !collisions[second].include?(first)
|
78
|
+
@collisions += 1
|
79
|
+
collisions[first] ||= []
|
80
|
+
collisions[first] << second
|
81
|
+
end
|
82
|
+
end
|
89
83
|
end
|
90
84
|
end
|
91
85
|
end
|
@@ -96,12 +90,43 @@ module Arbiter
|
|
96
90
|
unique_collisions << [first,second]
|
97
91
|
end
|
98
92
|
end
|
93
|
+
|
99
94
|
run_callbacks unique_collisions
|
100
95
|
end
|
101
96
|
|
102
97
|
def collide?(object, other)
|
103
|
-
|
104
|
-
|
98
|
+
if !other.is? :collidable
|
99
|
+
binding.pry
|
100
|
+
end
|
101
|
+
case object.collidable_shape
|
102
|
+
when :circle
|
103
|
+
case other.collidable_shape
|
104
|
+
when :circle
|
105
|
+
collide_circle_circle? object, other
|
106
|
+
when :aabb
|
107
|
+
collide_circle_aabb? object, other
|
108
|
+
when :polygon
|
109
|
+
collide_circle_polygon? object, other
|
110
|
+
end
|
111
|
+
when :aabb
|
112
|
+
case other.collidable_shape
|
113
|
+
when :circle
|
114
|
+
collide_aabb_circle? object, other
|
115
|
+
when :aabb
|
116
|
+
collide_aabb_aabb? object, other
|
117
|
+
when :polygon
|
118
|
+
collide_aabb_polygon? object, other
|
119
|
+
end
|
120
|
+
when :polygon
|
121
|
+
case other.collidable_shape
|
122
|
+
when :circle
|
123
|
+
collide_polygon_circle? object, other
|
124
|
+
when :aabb
|
125
|
+
collide_polygon_aabb? object, other
|
126
|
+
when :polygon
|
127
|
+
collide_polygon_polygon? object, other
|
128
|
+
end
|
129
|
+
end
|
105
130
|
end
|
106
131
|
|
107
132
|
def collide_circle_circle?(object, other)
|
@@ -110,8 +135,10 @@ module Arbiter
|
|
110
135
|
x_prime = other.center_x
|
111
136
|
y_prime = other.center_y
|
112
137
|
|
113
|
-
|
114
|
-
|
138
|
+
x_delta = x_prime - x
|
139
|
+
x_dist = x_delta * x_delta
|
140
|
+
y_delta = y_prime - y
|
141
|
+
y_dist = y_delta * y_delta
|
115
142
|
|
116
143
|
total_radius = object.radius + other.radius
|
117
144
|
x_dist + y_dist <= (total_radius * total_radius)
|
data/lib/gamebox/behavior.rb
CHANGED
@@ -56,11 +56,11 @@ class Behavior
|
|
56
56
|
@actor.instance_eval do
|
57
57
|
(class << self; self; end).class_eval do
|
58
58
|
methods.each do |meth|
|
59
|
-
log("redefining #{meth} for #{@actor.class}") if @actor.respond_to? meth
|
59
|
+
# log("redefining #{meth} for #{@actor.class}") if @actor.respond_to? meth
|
60
60
|
target.relegated_methods << meth
|
61
61
|
|
62
|
-
define_method meth do |*args|
|
63
|
-
target.send meth, *args
|
62
|
+
define_method meth do |*args, &block|
|
63
|
+
target.send meth, *args, &block
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
5
|
|
6
6
|
# available collidable_shapes are :circle, :polygon, :aabb
|
7
7
|
class Collidable < Behavior
|
@@ -22,6 +22,11 @@ class Collidable < Behavior
|
|
22
22
|
@actor.stage.register_collidable @actor
|
23
23
|
end
|
24
24
|
|
25
|
+
def removed
|
26
|
+
@actor.stage.unregister_collidable @actor
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
25
30
|
def build_shape
|
26
31
|
shape = nil
|
27
32
|
@collidable_shape = opts[:shape]
|
@@ -1,8 +1,33 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
|
3
3
|
class AaBbCollidable < CollidableShape
|
4
4
|
attr_accessor :cw_local_points
|
5
5
|
|
6
|
+
def setup
|
7
|
+
@collidable_shape = opts[:shape]
|
8
|
+
|
9
|
+
@cw_local_points = opts[:cw_local_points]
|
10
|
+
@cw_local_points ||= opts[:points]
|
11
|
+
@cw_world_points ||= build_aabb
|
12
|
+
|
13
|
+
@radius = opts[:radius]
|
14
|
+
@radius ||= calculate_radius
|
15
|
+
|
16
|
+
@old_x = actor_x
|
17
|
+
@old_y = actor_y
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_aabb
|
21
|
+
w = @actor.width
|
22
|
+
h = @actor.height
|
23
|
+
[
|
24
|
+
[0,0],
|
25
|
+
[w,0],
|
26
|
+
[w,h],
|
27
|
+
[0,h]
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
6
31
|
# TODO infinite loop if actor hasn't defined width and it gets relegated to us
|
7
32
|
def calculate_radius
|
8
33
|
w = @actor.width
|