lib/gamebox/arbiter.rb in gamebox-0.0.9 vs lib/gamebox/arbiter.rb in gamebox-0.1.0
- old
+ new
@@ -1,21 +1,24 @@
# this module gets mixed into a stage to allow it to handle collision detection
module Arbiter
def register_collidable(actor)
+ @spatial_hash = stagehand(:spatial)
@collidable_actors ||= []
unless @collidable_actors.include? actor
actor.when :remove_me do
unregister_collidable actor
end
@collidable_actors << actor
+ @spatial_hash.add(actor)
end
end
def unregister_collidable(actor)
@collidable_actors ||= []
@collidable_actors.delete actor
+ @spatial_hash.remove(actor)
end
def on_collision_of(first_objs, second_objs, &block)
first_objs = [first_objs].flatten
second_objs = [second_objs].flatten
@@ -31,34 +34,49 @@
@collision_handlers[sobj][fobj] = block
end
end
end
+ def run_callbacks(collisions)
+ collisions.each do |collision|
+ first = collision.first
+ second = collision.last
+
+ colliders = @collision_handlers[first.actor_type]
+ callback = colliders[second.actor_type] unless colliders.nil?
+ callback.call first, second unless callback.nil?
+ end
+ end
+
def find_collisions
@collidable_actors ||= []
- collisions = []
tmp_collidable_actors = @collidable_actors.dup
+ collisions = {}
@collidable_actors.each do |first|
+ x = first.x - @spatial_hash.cell_size
+ y = first.y - @spatial_hash.cell_size
+ w = @spatial_hash.cell_size * 3
+ h = w
+ tmp_collidable_actors = @spatial_hash.items_in(x,y,w,h)
- tmp_collidable_actors.delete first
-
tmp_collidable_actors.each do |second|
- if collide?(first, second)
- collisions << [first,second]
+ if first != second && collide?(first, second)
+ collisions[second] ||= []
+ if !collisions[second].include?(first)
+ collisions[first] ||= []
+ collisions[first] << second
+ end
end
end
-
end
-
- collisions.each do |collision|
- first = collision.first
- second = collision.last
-
- colliders = @collision_handlers[first.actor_type]
- callback = colliders[second.actor_type] unless colliders.nil?
- callback.call first, second unless callback.nil?
+ unique_collisions = []
+ collisions.each do |first,seconds|
+ seconds.each do |second|
+ unique_collisions << [first,second]
+ end
end
+ run_callbacks unique_collisions
end
def collide?(object, other)
self.send "collide_#{object.shape}_#{object.shape}?", object, other
end