gamebox 0.3.2 → 0.3.3

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 CHANGED
@@ -1,2 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
  gemspec
3
+ # gem 'perftools.rb', :git => 'git://github.com/bearded/perftools.rb.git', :branch => 'perftools-1.8'
data/gamebox.gemspec CHANGED
@@ -25,12 +25,9 @@ Gem::Specification.new do |s|
25
25
  s.add_dependency "tween"
26
26
  s.add_dependency "require_all"
27
27
  s.add_dependency "kvo"
28
- s.add_dependency "pry", '0.9.6'
29
- s.add_dependency "pry-remote"
30
-
31
- # TODO make this optional
32
- s.add_dependency "chipmunk"
33
28
 
29
+ s.add_development_dependency "pry", '~>0.9.7'
30
+ s.add_development_dependency "pry-remote"
34
31
  s.add_development_dependency "rspec-core"
35
32
  s.add_development_dependency "rspec-mocks"
36
33
  s.add_development_dependency "rspec-expectations"
@@ -38,7 +35,6 @@ Gem::Specification.new do |s|
38
35
  s.add_development_dependency "rspec"
39
36
  s.add_development_dependency "rake"
40
37
  s.add_development_dependency "polaris"
41
- s.add_development_dependency 'rcov'
42
38
 
43
39
  end
44
40
 
data/lib/gamebox.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  GAMEBOX_PATH = File.join(File.dirname(__FILE__),"gamebox/")
2
- require 'chipmunk'
3
2
  require 'diy'
4
3
  require 'constructor'
5
4
  require 'kvo'
@@ -16,5 +15,10 @@ def log(output, level = :debug)
16
15
  puts "[#{t.min}:#{t.sec}:#{t.usec}] [#{level}] #{output}"
17
16
  end
18
17
 
18
+ begin
19
+ require 'chipmunk'
20
+ rescue LoadError
21
+ end
22
+
19
23
  require 'require_all'
20
24
  require_all Dir.glob("#{GAMEBOX_PATH}/**/*.rb").reject { |f| f.match("template_app") || f.match("spec") || f.match("gamebox_application.rb")}
@@ -16,19 +16,19 @@ end
16
16
  class CollidableDebuggerView < ActorView
17
17
 
18
18
  def setup
19
- @color = Color[:white]
19
+ @color = Color::WHITE
20
20
  end
21
21
 
22
- def draw(target,x_off,y_off)
22
+ def draw(target,x_off,y_off,z)
23
23
  collider = @actor.actor
24
24
  case collider.collidable_shape
25
25
  when :circle
26
- target.draw_circle [x_off+collider.center_x, y_off+collider.center_y], collider.radius, @color
26
+ target.draw_circle x_off+collider.center_x, y_off+collider.center_y, collider.radius, @color, z
27
27
  else
28
28
  collider.cw_world_lines.each do |line|
29
29
  f = line.first
30
30
  l = line.last
31
- target.draw_line [x_off+f[0],y_off+f[1]],[x_off+l[0],y_off+l[1]], @color
31
+ target.draw_line x_off+f[0],y_off+f[1],x_off+l[0],y_off+l[1], @color, z
32
32
  end
33
33
  end
34
34
  end
@@ -1,23 +1,8 @@
1
- class FpsView < ActorView
2
- def draw(target,x_off,y_off)
3
- text = @actor.fps.to_s
4
- text = '0'*(6-text.size)+text if text.size < 6
1
+ class FpsView < LabelView; end
2
+ class Fps < Label
5
3
 
6
- font = @stage.resource_manager.load_font 'Asimov.ttf', 30
7
- text_image = font.render text, true, [250,250,250,255]
8
-
9
- x = @actor.x
10
- y = @actor.y
11
-
12
- text_image.blit target.screen, [x,y]
13
- end
14
- end
15
- class Fps < Actor
16
-
17
- has_behavior :layered => {:layer => 999}
18
-
19
- def fps
20
- input_manager.current_framerate.round
4
+ def text
5
+ fps
21
6
  end
22
7
 
23
8
  end
@@ -130,18 +130,13 @@ module Arbiter
130
130
  end
131
131
 
132
132
  def collide_circle_circle?(object, other)
133
- x = object.center_x
134
- y = object.center_y
135
- x_prime = other.center_x
136
- y_prime = other.center_y
137
-
138
- x_delta = x_prime - x
133
+ x_delta = other.center_x - object.center_x
139
134
  x_dist = x_delta * x_delta
140
- y_delta = y_prime - y
135
+ y_delta = other.center_y - object.center_y
141
136
  y_dist = y_delta * y_delta
142
137
 
143
138
  total_radius = object.radius + other.radius
144
- x_dist + y_dist <= (total_radius * total_radius)
139
+ (x_dist + y_dist) <= (total_radius * total_radius)
145
140
  end
146
141
 
147
142
  # Idea from:
@@ -86,14 +86,14 @@ class Physical < Behavior
86
86
  when :circle
87
87
  @radius = @opts[:radius]
88
88
 
89
- @moment_of_inertia ||= @opts[:fixed] ? Float::INFINITY : moment_for_circle(@mass, @radius, 0, ZERO_VEC_2)
89
+ @moment_of_inertia ||= @opts[:fixed] ? Float::INFINITY : CP::moment_for_circle(@mass, @radius, 0, ZERO_VEC_2)
90
90
  @body = CP::Body.new(@mass, @moment_of_inertia)
91
91
  @shape = CP::Shape::Circle.new(@body, @radius, ZERO_VEC_2)
92
92
 
93
93
  when :poly
94
94
  shape_array = @opts[:verts].collect{|v| vec2(v[0],v[1])}
95
95
 
96
- @moment_of_inertia ||= @opts[:fixed] ? Float::INFINITY : moment_for_poly(@mass, shape_array, ZERO_VEC_2)
96
+ @moment_of_inertia ||= @opts[:fixed] ? Float::INFINITY : CP::moment_for_poly(@mass, shape_array, ZERO_VEC_2)
97
97
  @body = CP::Body.new(@mass, @moment_of_inertia)
98
98
  @shape = CP::Shape::Poly.new(@body, shape_array, ZERO_VEC_2)
99
99
  verts = @opts[:verts].dup
@@ -51,19 +51,22 @@ class InputManager
51
51
  @window.when :button_down do |button_id|
52
52
  _handle_event button_id, :down
53
53
  end
54
+
54
55
  @window.when :update do |millis|
55
56
 
56
- @last_mouse_x ||= mouse_x
57
- @last_mouse_y ||= mouse_y
57
+ if @uses_mouse
58
+ @last_mouse_x ||= mouse_x
59
+ @last_mouse_y ||= mouse_y
58
60
 
59
- x_diff = @last_mouse_x - mouse_x
60
- y_diff = @last_mouse_y - mouse_y
61
+ x_diff = @last_mouse_x - mouse_x
62
+ y_diff = @last_mouse_y - mouse_y
61
63
 
62
- unless x_diff < 0.1 && x_diff > -0.1 && y_diff < 0.1 && y_diff > -0.1
63
- _handle_event nil, :motion
64
+ unless x_diff < 0.1 && x_diff > -0.1 && y_diff < 0.1 && y_diff > -0.1
65
+ _handle_event nil, :motion
64
66
 
65
- @last_mouse_x = mouse_x
66
- @last_mouse_y = mouse_y
67
+ @last_mouse_x = mouse_x
68
+ @last_mouse_y = mouse_y
69
+ end
67
70
  end
68
71
 
69
72
  game.update millis
@@ -112,21 +115,21 @@ class InputManager
112
115
  event_type = :game_pad
113
116
  end
114
117
 
115
- event = {
116
- :type => event_type,
117
- :id => gosu_id,
118
- :action => action,
119
- :callback_key => callback_key,
120
- :data => event_data
121
- }
118
+ # single threaded.. keep same event
119
+ @event ||= {}
120
+ @event[:type] = event_type
121
+ @event[:id] = gosu_id
122
+ @event[:action] = action
123
+ @event[:callback_key] = callback_key
124
+ @event[:data] = event_data
122
125
 
123
- fire_event(event)
126
+ fire_event(@event)
124
127
 
125
128
  if mouse_dragged
126
129
  drag_data = {:to => [mouse_x, mouse_y], :from => [@last_click_x, @last_click_y]}
127
- event[:data] = drag_data
128
- event[:callback_key] = :mouse_drag
129
- fire_event(event)
130
+ @event[:data] = drag_data
131
+ @event[:callback_key] = :mouse_drag
132
+ fire_event(@event)
130
133
  end
131
134
  end
132
135
 
@@ -178,11 +181,13 @@ class InputManager
178
181
  return unless block_given?
179
182
  @hooks[event_class] ||= {}
180
183
  for event_id in event_ids
184
+ @uses_mouse = true if event_id >= MsRangeBegin && event_id <= MsRangeEnd
181
185
  @hooks[event_class][event_id] ||= []
182
186
  @hooks[event_class][event_id] << block
183
187
  end
184
188
  @non_id_hooks[event_class] ||= []
185
189
  if event_ids.empty?
190
+ @uses_mouse = true
186
191
  @non_id_hooks[event_class] << block
187
192
  end
188
193
  if listener.respond_to?(:can_fire?) && listener.can_fire?(:remove_me)
@@ -1,35 +1,32 @@
1
- def vec2(*args)
2
- CP::Vec2.new *args
3
- end
4
-
5
- def moment_for_circle(*args)
6
- CP.moment_for_circle(*args)
7
- end
8
-
9
- def moment_for_poly(*args)
10
- CP.moment_for_poly(*args)
11
- end
12
-
13
- ZERO_VEC_2 = vec2(0,0)
1
+ if defined? CP
2
+ ZERO_VEC_2 = vec2(0,0)
3
+ def vec2(*args)
4
+ CP::Vec2.new *args
5
+ end
14
6
 
15
- class CP::Space
16
- alias :add_collision_func_old :add_collision_func
17
-
18
- # allows for passing arrays of collision types not just single ones
19
- # add_collision_func([:foo,:bar], [:baz,:yar]) becomes:
20
- # add_collision_func(:foo, :baz)
21
- # add_collision_func(:foo, :yar)
22
- # add_collision_func(:bar, :baz)
23
- # add_collision_func(:bar, :yar)
24
- def add_collision_func(first_objs, second_objs, &block)
25
- firsts = [first_objs].flatten
26
- seconds = [second_objs].flatten
7
+ class CP::Space
8
+ alias :add_collision_func_old :add_collision_func
27
9
 
28
- firsts.each do |f|
29
- seconds.each do |s|
30
- add_collision_func_old(f,s,&block)
10
+ # allows for passing arrays of collision types not just single ones
11
+ # add_collision_func([:foo,:bar], [:baz,:yar]) becomes:
12
+ # add_collision_func(:foo, :baz)
13
+ # add_collision_func(:foo, :yar)
14
+ # add_collision_func(:bar, :baz)
15
+ # add_collision_func(:bar, :yar)
16
+ def add_collision_func(first_objs, second_objs, &block)
17
+ firsts = [first_objs].flatten
18
+ seconds = [second_objs].flatten
19
+
20
+ firsts.each do |f|
21
+ seconds.each do |s|
22
+ add_collision_func_old(f,s,&block)
23
+ end
31
24
  end
32
25
  end
33
26
  end
34
-
27
+ else
28
+ ZERO_VEC_2 = Ftor.new(0,0)
29
+ def vec2(*args)
30
+ Ftor.new *args
31
+ end
35
32
  end
@@ -89,7 +89,7 @@ class ResourceManager
89
89
  end
90
90
  cached_img = Image.new(@window, full_name)
91
91
  rescue Exception => ex
92
- log "Cannot load image #{file_name}", :warn
92
+ # log "Cannot load image #{file_name}", :warn
93
93
  end
94
94
  @loaded_images[file_name] = cached_img
95
95
  end
@@ -28,6 +28,7 @@ class SoundManager
28
28
  end if files
29
29
 
30
30
  @sounds = {}
31
+ @playing_sounds = {}
31
32
  files = Dir.glob "#{SOUND_PATH}**.{#{SUPPORTED_AUDIO_EXTS.join(',')}}"
32
33
  for f in files
33
34
  name = File.basename(f)
@@ -50,7 +51,8 @@ class SoundManager
50
51
  # play_sound :foo # play sound at 100% volume
51
52
  def play_sound(what, opts={})
52
53
  if @enabled && @sounds[what]
53
- @sounds[what].play #opts
54
+ merged_opts = {volume:1, speed:1, looping:false}.merge opts
55
+ @playing_sounds[what] = @sounds[what].play merged_opts[:volume], merged_opts[:speed], merged_opts[:looping]
54
56
  end
55
57
  end
56
58
 
@@ -79,7 +81,7 @@ class SoundManager
79
81
  # stop_sound :foo
80
82
  def stop_sound(what)
81
83
  if @enabled
82
- @sounds[what].stop if @sounds[what]
84
+ @playing_sounds[what].stop if @playing_sounds[what]
83
85
  end
84
86
  end
85
87
 
@@ -0,0 +1,9 @@
1
+ class SpatialBucket < Array
2
+ attr_accessor :x, :y
3
+ def initialize(x,y)
4
+ @x = x
5
+ @y = y
6
+ super()
7
+ end
8
+ end
9
+
@@ -4,10 +4,11 @@ class SpatialHash
4
4
  attr_accessor :auto_resize
5
5
 
6
6
  def initialize(cell_size, resize = false)
7
- @cell_size = cell_size.to_f
7
+ @cell_size = cell_size.to_i
8
8
  @items = {}
9
9
  @auto_resize = resize
10
10
 
11
+ # TODO auto resize is broken atm
11
12
  if @auto_resize
12
13
  @total_w = 0
13
14
  @total_h = 0
@@ -18,12 +19,13 @@ class SpatialHash
18
19
  end
19
20
 
20
21
  def cell_size=(new_size)
21
- @cell_size = new_size
22
+ @cell_size = new_size.to_i
22
23
  rehash
23
24
  end
24
25
 
25
26
  def rehash
26
27
  @moved_items = {}
28
+ # TODO WTF?
27
29
  return
28
30
  items = @items
29
31
 
@@ -33,7 +35,7 @@ class SpatialHash
33
35
  avg_w = @total_w / items.size
34
36
  avg_h = @total_h / items.size
35
37
 
36
- @cell_size = (avg_w+avg_h)
38
+ @cell_size = (avg_w+avg_h).to_i
37
39
  end
38
40
 
39
41
  @total_w = 0
@@ -61,12 +63,9 @@ class SpatialHash
61
63
  def _add(item)
62
64
  buckets = lookup item
63
65
  @items[item] = buckets
66
+
64
67
  buckets.each do |bucket|
65
- x,y = *bucket
66
- @buckets[x] ||= {}
67
- @buckets[x][y] ||= []
68
- target_bucket = @buckets[x][y]
69
- target_bucket << item
68
+ bucket << item
70
69
 
71
70
  if @auto_resize
72
71
  w = item.width if item.respond_to? :width
@@ -85,13 +84,12 @@ class SpatialHash
85
84
  end
86
85
 
87
86
  def _remove(item)
88
- buckets = @items[item]
89
- (buckets || []).each do |bucket|
90
- x,y = *bucket
91
- return if @buckets[x].nil? || @buckets[x][y].nil?
92
- @buckets[x][y].delete item
87
+ buckets = @items.delete item
88
+ if buckets
89
+ buckets.each do |bucket|
90
+ bucket.delete item
91
+ end
93
92
  end
94
- @items.delete item
95
93
  end
96
94
 
97
95
  def lookup(item)
@@ -103,34 +101,39 @@ class SpatialHash
103
101
 
104
102
  x = item.x
105
103
  y = item.y
106
- min_x, min_y = bucket_for x, y
104
+ min_x = bucket_cell_for x
105
+ min_y = bucket_cell_for y
107
106
  if w == 1 && h == 1
108
107
  max_x = min_x
109
108
  max_y = min_y
110
109
  else
111
- max_x, max_y = bucket_for x+w-1, y+h-1
110
+ max_x = bucket_cell_for x+w-1
111
+ max_y = bucket_cell_for y+h-1
112
112
  end
113
113
 
114
114
  buckets = []
115
- (max_x-min_x+1).times do |i|
116
- bucket_x = min_x + i
117
- (max_y-min_y+1).times do |j|
118
- buckets << [bucket_x,min_y+j]
115
+ bucket_x = min_x
116
+ while bucket_x < max_x + 1 do
117
+ bucket_y = min_y
118
+ while bucket_y < max_y + 1 do
119
+ @buckets[bucket_x] ||= {}
120
+ @buckets[bucket_x][bucket_y] ||= SpatialBucket.new(bucket_x, bucket_y)
121
+ buckets << @buckets[bucket_x][bucket_y]
122
+ bucket_y += 1
119
123
  end
124
+ bucket_x += 1
120
125
  end
121
126
 
122
127
  buckets
123
128
  end
124
129
 
125
- def bucket_for(x,y)
126
- bucket_x = (x/cell_size).floor
127
- bucket_y = (y/cell_size).floor
128
- return [bucket_x, bucket_y]
130
+ def bucket_cell_for(location)
131
+ (location.to_i / cell_size).to_i
129
132
  end
130
-
133
+
131
134
  def items_at(x,y)
132
- bucket_x = (x/@cell_size).floor
133
- bucket_y = (y/@cell_size).floor
135
+ bucket_x = bucket_cell_for x
136
+ bucket_y = bucket_cell_for y
134
137
  if @buckets[bucket_x].nil? || @buckets[bucket_x][bucket_y].nil?
135
138
  return []
136
139
  else
@@ -141,12 +144,14 @@ class SpatialHash
141
144
  def items_in(x,y,w,h)
142
145
  return items_at x, y if ((w.nil? || w == 1) && (h.nil? || w == 1))
143
146
 
144
- min_x, min_y = bucket_for x, y
147
+ min_x = bucket_cell_for x
148
+ min_y = bucket_cell_for y
145
149
  if w == 1 && h == 1
146
150
  max_x = min_x
147
151
  max_y = min_y
148
152
  else
149
- max_x, max_y = bucket_for x+w-1, y+h-1
153
+ max_x = bucket_cell_for x+w-1
154
+ max_y = bucket_cell_for y+w-1
150
155
  end
151
156
 
152
157
  items_in_bucket_range min_x, min_y, max_x, max_y
@@ -175,14 +180,11 @@ class SpatialHash
175
180
  # occupied by the item
176
181
  def neighbors_of(item, dist=1)
177
182
  buckets = lookup(item)
178
- min_bucket_x, min_bucket_y = *buckets.first
179
- max_bucket_x, max_bucket_y = *buckets.last
180
-
181
- min_bucket_x = min_bucket_x-1
182
- min_bucket_y = min_bucket_y-1
183
183
 
184
- max_bucket_x = max_bucket_x+1
185
- max_bucket_y = max_bucket_y+1
184
+ min_bucket_x = buckets.min_by{ |bucket| bucket.x }.x - dist
185
+ min_bucket_y = buckets.min_by{ |bucket| bucket.y }.y - dist
186
+ max_bucket_x = buckets.max_by{ |bucket| bucket.x }.x + dist
187
+ max_bucket_y = buckets.max_by{ |bucket| bucket.y }.y + dist
186
188
 
187
189
  items = items_in_bucket_range min_bucket_x, min_bucket_y, max_bucket_x, max_bucket_y
188
190
  items-[item]