gamebox 0.2.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|