/** * \brief Checks whether a sprite collides with this detector. * * If there is a collision, the notify_collision(MapEntity&, Sprite&, Sprite&) method is called. * * \param entity the entity to check * \param sprite the sprite of that entity */ void Detector::check_collision(MapEntity& entity, Sprite& sprite) { if (has_collision_mode(COLLISION_SPRITE) && &entity != this && (has_layer_independent_collisions() || get_layer() == entity.get_layer())) { // we check the collision between the specified entity's sprite and all sprites of the current entity std::vector<Sprite*>::const_iterator it; for (it = get_sprites().begin(); it != get_sprites().end(); it++) { Sprite& this_sprite = *(*it); if (this_sprite.test_collision(sprite, get_x(), get_y(), entity.get_x(), entity.get_y())) { notify_collision(entity, sprite, this_sprite); } } } }
/** * @brief Removes and destroys the entities placed in the entities_to_remove list. */ void MapEntities::remove_marked_entities() { list<MapEntity*>::iterator it; // remove the marked entities for (it = entities_to_remove.begin(); it != entities_to_remove.end(); it++) { MapEntity *entity = *it; Layer layer = entity->get_layer(); // remove it from the obstacle entities list if present if (entity->can_be_obstacle()) { if (entity->has_layer_independent_collisions()) { for (int i = 0; i < LAYER_NB; i++) { obstacle_entities[i].remove(entity); } } else { obstacle_entities[layer].remove(entity); } } // remove it from the detectors list if present if (entity->can_detect_entities()) { detectors.remove((Detector*) entity); } // remove it from the sprite entities list if present if (entity->is_displayed_in_y_order()) { entities_displayed_y_order[layer].remove(entity); } else if (entity->can_be_displayed()) { entities_displayed_first[layer].remove(entity); } // remove it from the whole list all_entities.remove(entity); // destroy it delete entity; } entities_to_remove.clear(); }
/** * \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(MapEntity& 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() == NULL) { // 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); } } }
/** * \brief Changes the layer of an entity. * * Only some specific entities should change their layer. * * \param entity an entity * \param layer the new layer */ void MapEntities::set_entity_layer(MapEntity& entity, Layer layer) { Layer old_layer = entity.get_layer(); if (layer != old_layer) { // update the obstacle list if (entity.can_be_obstacle() && !entity.has_layer_independent_collisions()) { obstacle_entities[old_layer].remove(&entity); obstacle_entities[layer].push_back(&entity); } // update the ground observers list if (entity.is_ground_observer()) { ground_observers[old_layer].remove(&entity); ground_observers[layer].push_back(&entity); } // update the ground modifiers list if (entity.is_ground_modifier()) { ground_modifiers[old_layer].remove(&entity); ground_modifiers[layer].push_back(&entity); } // update the sprites list if (entity.is_drawn_in_y_order()) { entities_drawn_y_order[old_layer].remove(&entity); entities_drawn_y_order[layer].push_back(&entity); } else if (entity.can_be_drawn()) { entities_drawn_first[old_layer].remove(&entity); entities_drawn_first[layer].push_back(&entity); } // update the entity after the lists because this function might be called again entity.set_layer(layer); } }
/** * \brief Removes and destroys the entities placed in the entities_to_remove list. */ void MapEntities::remove_marked_entities() { list<MapEntity*>::iterator it; // remove the marked entities for (it = entities_to_remove.begin(); it != entities_to_remove.end(); it++) { MapEntity* entity = *it; Layer layer = entity->get_layer(); // remove it from the obstacle entities list if present if (entity->can_be_obstacle()) { if (entity->has_layer_independent_collisions()) { for (int i = 0; i < LAYER_NB; i++) { obstacle_entities[i].remove(entity); } } else { obstacle_entities[layer].remove(entity); } } // remove it from the detectors list if present if (entity->is_detector()) { detectors.remove(static_cast<Detector*>(entity)); } // remove it from the ground obsevers list if present if (entity->is_ground_observer()) { ground_observers[layer].remove(entity); } // remove it from the ground modifiers list if present if (entity->is_ground_modifier()) { ground_modifiers[layer].remove(entity); } // remove it from the sprite entities list if present if (entity->is_drawn_in_y_order()) { entities_drawn_y_order[layer].remove(entity); } else if (entity->can_be_drawn()) { entities_drawn_first[layer].remove(entity); } // remove it from the whole list all_entities.remove(entity); const std::string& name = entity->get_name(); if (!name.empty()) { named_entities.erase(name); } // update the specific entities lists switch (entity->get_type()) { case STAIRS: stairs[layer].remove(static_cast<Stairs*>(entity)); break; case CRYSTAL_BLOCK: crystal_blocks[layer].remove(static_cast<CrystalBlock*>(entity)); break; case SEPARATOR: separators.remove(static_cast<Separator*>(entity)); break; case BOOMERANG: this->boomerang = NULL; break; default: break; } // destroy it destroy_entity(entity); } entities_to_remove.clear(); }