class IMICFPS class CollisionManager attr_reader :game_state, :collisions def initialize(game_state:) @game_state = game_state @collisions = {} @aabb_tree = AABBTree.new @physics_manager = PhysicsManager.new(collision_manager: self) end def add(entity) @aabb_tree.insert(entity, entity.bounding_box) end def update @game_state.entities.each do |entity| next unless entity.is_a?(Entity) next unless node = @aabb_tree.objects[entity] unless entity.bounding_box == node.bounding_box puts "Updating #{entity.class}" @aabb_tree.update(entity, entity.bounding_box.clone) end end check_broadphase @physics_manager.update end def search(collider) @aabb_tree.search(collider) end def remove(entity) @aabb_tree.remove(entity) end def check_broadphase # FIXME: Cache collisions to speed things up @collisions.clear broadphase = {} @game_state.entities.each do |entity| next unless entity.collidable? next if entity.collision == :static # Only dynamic entities can be resolved search = @aabb_tree.search(entity.bounding_box) if search.size > 0 search.reject! {|ent| ent == entity || !ent.collidable?} broadphase[entity] = search end end broadphase.each do |entity, _collisions| _collisions.each do |ent| # aabb vs aabb next unless entity.bounding_box.intersect?(ent.bounding_box) # entity model aabb tree vs ent model aabb tree ent_tree_search = ent.model.aabb_tree.search(localize_entity_bounding_box(entity, ent), true) next if ent_tree_search.size == 0 # puts "#{ent.class} -> #{ent_tree_search.size} (#{Gosu.milliseconds})" entity.position.y = ent_tree_search.first.object.vertices.first.y if entity.is_a?(Player) && ent.is_a?(Terrain) @collisions[entity] = _collisions end end end # AABBTree on entities is relative to model origin of 0,0,0 def localize_entity_bounding_box(entity, target) return entity.bounding_box if target.position == 0 && target.rotation == 0 # "tranform" entity bounding box into target's space local = (target.position) # needs tweaking, works well enough for now box = entity.bounding_box.clone box.min -= local box.max -= local return box end end end