/** * \brief Checks whether an entity collides with this detector. * * This function is called by the map when an entity has just moved. * It checks whether the entity collides with this detector. * Depending on the detector collision mode(s), the appropriate * test_collision_* functions are called. * If there is a collision, the notify_collision() method is called. * * \param entity the entity to check */ void Detector::check_collision(Entity& entity) { if (&entity != this && (has_layer_independent_collisions() || get_layer() == entity.get_layer())) { // the entity is in the same layer as the detector // detect the collision depending on the collision mode if (has_collision_mode(COLLISION_OVERLAPPING) && test_collision_rectangle(entity)) { notify_collision(entity, COLLISION_OVERLAPPING); } if (has_collision_mode(COLLISION_CONTAINING) && test_collision_inside(entity)) { notify_collision(entity, COLLISION_CONTAINING); } if (has_collision_mode(COLLISION_ORIGIN) && test_collision_origin_point(entity)) { notify_collision(entity, COLLISION_ORIGIN); } if (has_collision_mode(COLLISION_FACING) && test_collision_facing_point(entity)) { if (entity.get_facing_entity() == nullptr) { // make sure only one entity can think "I am the facing entity" entity.set_facing_entity(this); } notify_collision(entity, COLLISION_FACING); } if (has_collision_mode(COLLISION_TOUCHING) && test_collision_touching(entity)) { notify_collision(entity, COLLISION_TOUCHING); } if (has_collision_mode(COLLISION_CENTER) && test_collision_center(entity)) { notify_collision(entity, COLLISION_CENTER); } if (has_collision_mode(COLLISION_CUSTOM) && test_collision_custom(entity)) { notify_collision(entity, COLLISION_CUSTOM); } } }
/** * \copydoc Detector::test_collision_custom */ bool CustomEntity::test_collision_custom(MapEntity& entity) { if (!successful_collision_tests.empty()) { // Avoid reentrant collision tests. return false; } bool collision = false; const std::vector<CollisionInfo> collision_tests = this->collision_tests; for (const CollisionInfo& info: collision_tests) { switch (info.get_built_in_test()) { case COLLISION_OVERLAPPING: if (test_collision_rectangle(entity)) { collision = true; successful_collision_tests.push_back(info); } break; case COLLISION_CONTAINING: if (test_collision_inside(entity)) { collision = true; successful_collision_tests.push_back(info); } break; case COLLISION_ORIGIN: if (test_collision_origin_point(entity)) { collision = true; successful_collision_tests.push_back(info); } break; case COLLISION_FACING: if (test_collision_facing_point(entity)) { collision = true; successful_collision_tests.push_back(info); } break; case COLLISION_TOUCHING: if (test_collision_touching(entity)) { collision = true; successful_collision_tests.push_back(info); } break; case COLLISION_CENTER: if (test_collision_center(entity)) { collision = true; successful_collision_tests.push_back(info); } break; case COLLISION_CUSTOM: if (get_lua_context().do_custom_entity_collision_test_function( info.get_custom_test_ref(), *this, entity) ) { collision = true; successful_collision_tests.push_back(info); } break; case COLLISION_SPRITE: // Not handled here. break; case COLLISION_NONE: Debug::die("Invalid collision mode"); break; } } return collision; }