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