예제 #1
0
파일: Detector.cpp 프로젝트: j4b0l/solarus
/**
 * \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);
      }
    }
  }
}
예제 #2
0
파일: MapEntities.cpp 프로젝트: ziz/solarus
/**
 * @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();
}
예제 #3
0
파일: Detector.cpp 프로젝트: j4b0l/solarus
/**
 * \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);
    }
  }
}
예제 #4
0
/**
 * \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);
  }
}
예제 #5
0
/**
 * \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();
}