예제 #1
0
/**
 * \brief This function is called by the engine when an entity overlaps the pickable item.
 *
 * If the entity is the player, we give him the item, and the map is notified
 * to destroy it.
 * \param entity_overlapping the entity overlapping the detector
 * \param collision_mode the collision mode that detected the collision
 */
void Pickable::notify_collision(MapEntity& entity_overlapping, CollisionMode collision_mode) {

    if (entity_overlapping.is_hero()) {
        try_give_item_to_player();
    }
    else if (entity_followed == NULL) {

        if (entity_overlapping.get_type() == ENTITY_BOOMERANG) {
            Boomerang& boomerang = static_cast<Boomerang&>(entity_overlapping);
            if (!boomerang.is_going_back()) {
                boomerang.go_back();
            }
            entity_followed = &boomerang;
        }
        else if (entity_overlapping.get_type() == ENTITY_HOOKSHOT) {
            Hookshot& hookshot = static_cast<Hookshot&>(entity_overlapping);
            if (!hookshot.is_going_back()) {
                hookshot.go_back();
            }
            entity_followed = &hookshot;
        }

        if (entity_followed != NULL) {
            clear_movement();
            set_movement(new FollowMovement(entity_followed, 0, 0, true));
            falling_height = FALLING_NONE;
            set_blinking(false);
        }
    }
}
예제 #2
0
/**
 * \brief This function is called by the engine when an entity overlaps the pickable item.
 *
 * If the entity is the player, we give him the item, and the map is notified
 * to destroy it.
 * \param entity_overlapping the entity overlapping the detector
 * \param collision_mode the collision mode that detected the collision
 */
void Pickable::notify_collision(MapEntity& entity_overlapping, CollisionMode /* collision_mode */) {

  if (entity_overlapping.is_hero()) {
    try_give_item_to_player();
  }
  else if (entity_followed == nullptr) {

    MapEntityPtr shared_entity_overlapping =
        std::static_pointer_cast<MapEntity>(entity_overlapping.shared_from_this());
    if (entity_overlapping.get_type() == ENTITY_BOOMERANG) {
      Boomerang& boomerang = static_cast<Boomerang&>(entity_overlapping);
      if (!boomerang.is_going_back()) {
        boomerang.go_back();
      }
      entity_followed = shared_entity_overlapping;
    }
    else if (entity_overlapping.get_type() == ENTITY_HOOKSHOT) {
      Hookshot& hookshot = static_cast<Hookshot&>(entity_overlapping);
      if (!hookshot.is_going_back()) {
        hookshot.go_back();
      }
      entity_followed = shared_entity_overlapping;
    }

    if (entity_followed != nullptr) {
      clear_movement();
      set_movement(std::make_shared<FollowMovement>(
          entity_followed, 0, 0, true
      ));
      falling_height = FALLING_NONE;
      set_blinking(false);
    }
  }
}
예제 #3
0
/**
 * @brief Notifies this entity that another sprite is overlapping it.
 *
 * This function is called by check_collision(MapEntity*, Sprite*) when another entity's
 * sprite overlaps a sprite of this detector.
 *
 * @param other_entity the entity overlapping this detector
 * @param other_sprite the sprite of other_entity that is overlapping this detector
 * @param this_sprite the sprite of this detector that is overlapping the other entity's sprite
 */
void Destructible::notify_collision(MapEntity& other_entity,
    Sprite& other_sprite, Sprite& this_sprite) {

  if (features[subtype].can_be_cut
      && !is_being_cut
      && !is_disabled()
      && !is_regenerating
      && other_entity.is_hero()
      && other_sprite.contains("sword")) {

    Hero& hero = static_cast<Hero&>(other_entity);
    if (hero.is_striking_with_sword(*this)) {

      play_destroy_animation();
      hero.check_position(); // to update the ground under the hero
      create_pickable();

      if (can_explode()) {
        explode();
      }
    }
  }

  // TODO use dynamic dispatch
  if (other_entity.get_type() == EXPLOSION
      && can_explode()
      && !is_being_cut
      && !is_disabled()
      && !is_regenerating) {

    play_destroy_animation();
    create_pickable();
    explode();
  }
}
예제 #4
0
/**
 * @brief Notifies this detector that a collision was just detected with an entity.
 * @param entity_overlapping the entity overlapping the detector
 * @param collision_mode the collision mode that detected the collision (useful if
 * the detector has several collision modes)
 */
void DynamicTile::notify_collision(MapEntity &entity_overlapping, CollisionMode collision_mode) {

  if (entity_overlapping.is_hero()) {
    // tell the hero that he is on the ground of this tile
    Hero& hero = (Hero&) entity_overlapping;
    Ground ground = Map::obstacle_to_ground(tile_pattern->get_obstacle());
    hero.set_ground(ground);
  }
}
예제 #5
0
/**
 * \brief Notifies this entity that another sprite is overlapping it.
 *
 * This function is called by check_collision(MapEntity*, Sprite*) when another entity's
 * sprite overlaps a sprite of this detector.
 *
 * \param other_entity the entity overlapping this detector
 * \param other_sprite the sprite of other_entity that is overlapping this detector
 * \param this_sprite the sprite of this detector that is overlapping the other entity's sprite
 */
void Pickable::notify_collision(MapEntity& other_entity, Sprite& other_sprite,
                                Sprite& this_sprite) {

    // taking the item with the sword
    if (other_entity.is_hero()
            && other_sprite.contains("sword")) {

        try_give_item_to_player();
    }
}
예제 #6
0
/**
 * \brief This function is called when another entity overlaps this crystal block.
 * \param entity_overlapping the other entity
 * \param collision_mode the collision mode that detected the collision
 */
void CrystalBlock::notify_collision(MapEntity& entity_overlapping, CollisionMode collision_mode) {

  if (entity_overlapping.is_hero() && is_raised()) {

    // see if we have to make fim fall

    Hero& hero = static_cast<Hero&>(entity_overlapping);
    if (hero.can_control_movement()) {

      Rectangle collision_box = hero.get_bounding_box();
      int x1 = get_top_left_x();
      int x2 = x1 + get_width();
      int y1 = get_top_left_y();
      int y2 = y1 + get_height();
      int jump_direction = 0;
      int jump_length = 0;
      bool jumped = false;

      const Rectangle &hero_center = hero.get_center_point();

      if (hero_center.get_y() < y1) {
        // fall to the north
        collision_box.set_y(y1 - 16);
        jump_direction = 2;
        jump_length = hero.get_top_left_y() + 16 - y1;
        jumped = try_jump(hero, collision_box, jump_direction, jump_length);
      }
      else if (hero_center.get_y() >= y2) {
        // fall to the south
        collision_box.set_y(y2);
        jump_direction = 6;
        jump_length = y2 - hero.get_top_left_y();
        jumped = try_jump(hero, collision_box, jump_direction, jump_length);
      }

      if (!jumped) {
        if (hero_center.get_x() >= x2) {
          // fall to the east
          collision_box.set_x(x2);
          jump_direction = 0;
          jump_length = x2 - hero.get_top_left_x();
          try_jump(hero, collision_box, jump_direction, jump_length);
        }
        else if (hero_center.get_x() < x1) {
          // fall to the west
          collision_box.set_x(x1 - 16);
          jump_direction = 4;
          jump_length = hero.get_top_left_x() + 16 - x1;
          try_jump(hero, collision_box, jump_direction, jump_length);
        }
      }
    }
  }
}
예제 #7
0
/**
 * \copydoc Detector::notify_collision(MapEntity&, Sprite&, Sprite&)
 */
void Pickable::notify_collision(
    MapEntity& other_entity,
    Sprite& /* this_sprite */,
    Sprite& other_sprite
) {
  // taking the item with the sword
  if (other_entity.is_hero()) {
    Hero& hero = static_cast<Hero&>(other_entity);
    if (other_sprite.get_animation_set_id() == hero.get_hero_sprites().get_sword_sprite_id()) {
      try_give_item_to_player();
    }
  }
}
예제 #8
0
/**
 * @brief This function is called by the engine when an entity overlaps the shop item.
 *
 * If the entity is the hero, we allow him to buy the item.
 *
 * @param entity_overlapping the entity overlapping the detector
 * @param collision_mode the collision mode that detected the collision
 */
void ShopItem::notify_collision(MapEntity &entity_overlapping, CollisionMode collision_mode) {

  if (entity_overlapping.is_hero() && !get_game().is_suspended()) {

    Hero &hero = (Hero&) entity_overlapping;

    if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
        && hero.is_free()) {

      // we show the 'look' icon
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
예제 #9
0
/**
 * \brief This function is called by the engine when an entity overlaps the shop item.
 *
 * If the entity is the hero, we allow him to buy the item.
 *
 * \param entity_overlapping the entity overlapping the detector
 * \param collision_mode the collision mode that detected the collision
 */
void ShopTreasure::notify_collision(
    MapEntity& entity_overlapping, CollisionMode /* collision_mode */) {

  if (entity_overlapping.is_hero() && !get_game().is_suspended()) {

    Hero& hero = static_cast<Hero&>(entity_overlapping);

    if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
        && hero.is_free()) {

      // we show the 'look' icon
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
예제 #10
0
파일: Jumper.cpp 프로젝트: Arvek/SOLARME
/**
 * \brief Returns whether an entity's collides with this jumper.
 *
 * The result depends on the sensor's shape.
 *
 * \param entity the entity
 * \return true if the entity's collides with this jumper
 */
bool Jumper::test_collision_custom(MapEntity& entity) {

  if (!entity.is_hero()) {
    return false;
  }

  Hero& hero = static_cast<Hero&>(entity);
  const int direction8 = get_direction();

  if (!is_jump_diagonal()) {

    int expected_hero_direction4 = direction8 / 2;
    if (!hero.is_moving_towards(expected_hero_direction4)) {
      return false;
    }
  }

  return is_in_jump_position(hero);
}
예제 #11
0
/**
 * @brief Returns whether an entity's collides with this entity.
 * @param entity an entity
 * @return true if the entity's collides with this entity
 */
bool Teletransporter::test_collision_custom(MapEntity& entity) {

  bool collision = false;
  bool normal_case = true;

  // specific collision tests for some situations
  if (entity.is_hero()) {

    Hero& hero = (Hero&) entity;
    if (is_on_map_side()) {
      // scrolling towards an adjacent map
      Rectangle facing_point = hero.get_facing_point(transition_direction);
      collision = hero.is_moving_towards(transition_direction)
	    && overlaps(facing_point.get_x(), facing_point.get_y());
      normal_case = false;
    }

    else if (!get_map().test_collision_with_border(get_center_point()) &&
        hero.get_ground() == GROUND_HOLE) {
      // falling into a hole
      collision = overlaps(hero.get_ground_point());
      normal_case = false;
    }
  }

  // normal case
  if (normal_case) {
    const Rectangle& entity_rectangle = entity.get_bounding_box();
    int x1 = entity_rectangle.get_x() + 4;
    int x2 = x1 + entity_rectangle.get_width() - 9;
    int y1 = entity_rectangle.get_y() + 4;
    int y2 = y1 + entity_rectangle.get_height() - 9;

    collision = overlaps(x1, y1) && overlaps(x2, y1) &&
      overlaps(x1, y2) && overlaps(x2, y2);
  }

  if (!collision && !is_on_map_side()) {
    transporting_hero = false;
  }

  return collision;
}
예제 #12
0
파일: Door.cpp 프로젝트: lambdaloop/solarus
/**
 * @brief Notifies this detector that a collision was just detected with another entity.
 *
 * This function is called by the engine when there is a collision with another entity.
 *
 * @param entity_overlapping the entity overlapping the detector
 * @param collision_mode the collision mode that detected the collision
 */
void Door::notify_collision(MapEntity& entity_overlapping, CollisionMode collision_mode) {

  if (is_closed() && entity_overlapping.is_hero()) {

    Hero& hero = static_cast<Hero&>(entity_overlapping);

    if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
        && hero.is_free()) {

      if (can_open()) {
        // The action command opens the door.
        get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_OPEN);
      }
      else if (!get_cannot_open_dialog_id().empty()) {
        // The action command shows a dialog.
        get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
      }
    }
  }
}
예제 #13
0
/**
 * \copydoc Detector::notify_collision(MapEntity&, Sprite&, Sprite&)
 */
void Destructible::notify_collision(
    MapEntity& other_entity,
    Sprite& /* this_sprite */,
    Sprite& other_sprite
) {
  if (get_can_be_cut()
      && !is_being_cut
      && !is_waiting_for_regeneration()
      && !is_regenerating
      && other_entity.is_hero()) {

    Hero& hero = static_cast<Hero&>(other_entity);
    if (other_sprite.get_animation_set_id() == hero.get_hero_sprites().get_sword_sprite_id() &&
        hero.is_striking_with_sword(*this)) {

      play_destroy_animation();
      hero.check_position();  // To update the ground under the hero.
      create_treasure();

      get_lua_context().destructible_on_cut(*this);

      if (get_can_explode()) {
        explode();
      }
    }
  }

  // TODO use dynamic dispatch
  if (other_entity.get_type() == EntityType::EXPLOSION
      && get_can_explode()
      && !is_being_cut
      && !is_waiting_for_regeneration()
      && !is_regenerating) {

    play_destroy_animation();
    create_treasure();
    explode();
  }
}
예제 #14
0
파일: Jumper.cpp 프로젝트: xor-mind/solarus
/**
 * @brief Returns whether an entity's collides with this jumper.
 *
 * The result depends on the sensor's shape.
 *
 * @param entity the entity
 * @return true if the entity's collides with this jumper
 */
bool Jumper::test_collision_custom(MapEntity &entity) {

  if (!entity.is_hero()) {
    return false;
  }

  Hero &hero = (Hero&) entity;
  int direction8 = get_direction();

  // if the sensor's has one of the four main directions, then
  // its shape is exactly its rectangle
  if (direction8 % 2 == 0) {

    int expected_hero_direction4 = direction8 / 2;
    if (hero.get_ground() == GROUND_DEEP_WATER) {
      // if the hero is swimming, the jumper can be used the opposite way
      expected_hero_direction4 = (expected_hero_direction4 + 2) % 4;
    }

    if (!hero.is_moving_towards(expected_hero_direction4)) {
      return false;
    }

    bool horizontal = (direction8 % 4 == 0); // horizontal or vertical jumper
    const Rectangle &facing_point = hero.get_facing_point(expected_hero_direction4);
    return overlaps(facing_point.get_x() + (horizontal ? 0 : -8),
		    facing_point.get_y() + (horizontal ? -8 : 0))
      && overlaps(facing_point.get_x() + (horizontal ? 0 : 7),
		  facing_point.get_y() + (horizontal ? 7 : 0));
  }

  // otherwise, the sensor's shape is a diagonal bar

  return is_point_in_diagonal(hero.get_facing_point((direction8 - 1) / 2))
    || is_point_in_diagonal(hero.get_facing_point((direction8 + 1) % 8 / 2));
}
예제 #15
0
파일: Pickable.cpp 프로젝트: dujodujo/ape
void Pickable::notify_collision(MapEntity& entity_overlapping, CollisionMode collision_mode) {
	if(entity_overlapping.is_hero() && pickable) {
		remove_from_map();
		hero_pick_item();
	}
}