示例#1
0
文件: Jumper.cpp 项目: Arvek/SOLARME
/**
 * \brief Returns whether an entity is correctly placed to start jumping
 * with this jumper.
 * \param entity A map entity.
 * \return \c true if the entity is correctly placed to start the jump.
 */
bool Jumper::is_in_jump_position(const MapEntity& entity) const {

  const int direction8 = get_direction();

  if (is_jump_diagonal()) {
    // The sensor's shape is a diagonal bar.

    return is_point_in_diagonal(entity.get_facing_point((direction8 - 1) / 2))
      || is_point_in_diagonal(entity.get_facing_point((direction8 + 1) % 8 / 2));
  }

  // The sensor has one of the four main directions.
  // Its shape is exactly its rectangle.

  const int expected_direction4 = direction8 / 2;
  const Rectangle& facing_point = entity.get_facing_point(expected_direction4);
  const bool horizontal_jump = is_jump_horizontal();

  return overlaps(facing_point.get_x() + (horizontal_jump ? 0 : -8),
      facing_point.get_y() + (horizontal_jump ? -8 : 0))
    && overlaps(facing_point.get_x() + (horizontal_jump ? 0 : 7),
        facing_point.get_y() + (horizontal_jump ? 7 : 0));
}
示例#2
0
/**
 * \brief Returns whether the hero is correctly placed to
 * start jumping with this jumper.
 * \param hero The hero.
 * \param candidate_position The candidate bounding box.
 * \param extended_region Whether you want to consider the extended jumper
 * beyond its bounding box, or to keep it restricted to its bounding box.
 * \return \c true if the hero is correctly placed to start a jump.
 */
bool Jumper::is_in_jump_position(
    const Hero& hero,
    const Rectangle& candidate_position,
    bool extended_region) const {

  if (overlaps_jumping_region(candidate_position, extended_region)) {
    // Overlapping the active region: cannot start a jump from there.
    return false;
  }

  const int direction8 = get_direction();
  const int expected_hero_direction4 = direction8 / 2;

  if (is_jump_diagonal()) {
    // Diagonal case: The sensor's shape is a diagonal bar.

    // The player should move toward one of both directions.
    if (!hero.is_moving_towards(expected_hero_direction4) &&
        !hero.is_moving_towards((expected_hero_direction4 + 1) % 4)) {
      return false;
    }

    // Test if the appropriate corner of the hero crosses the diagonal.
    Point corner = {
        candidate_position.get_x() - 1,
        candidate_position.get_y() - 1
    };
    if (direction8 == 1 || direction8 == 7) {
      // Right-up or right-down.
      corner.x += candidate_position.get_width() + 1;
    }
    if (direction8 == 5 || direction8 == 7) {
      // Left-down or right-down.
      corner.y += candidate_position.get_height() + 1;
    }

    return extended_region ?
        is_point_in_extended_diagonal(corner) :
        is_point_in_diagonal(corner);
  }

  // Non-diagonal case: the sensor has one of the four main directions.
  // Its shape is exactly its rectangle.

  // The player should move toward the jumper's direction.
  if (!hero.is_moving_towards(expected_hero_direction4)) {
    return false;
  }

  Point facing_point;

  switch (expected_hero_direction4) {

    // right
    case 0:
      facing_point = {
          candidate_position.get_x() + 16,
          candidate_position.get_y() + 8
      };
      break;

      // up
    case 1:
      facing_point = {
          candidate_position.get_x() + 8,
          candidate_position.get_y() - 1
      };
      break;

      // left
    case 2:
      facing_point = {
          candidate_position.get_x() - 1,
          candidate_position.get_y() + 8
      };
      break;

      // down
    case 3:
      facing_point = {
          candidate_position.get_x() + 8,
          candidate_position.get_y() + 16
      };
      break;

    default:
      Debug::die("Invalid direction");
  }

  if (is_jump_horizontal()) {
    if (extended_region) {
      // Are we inside the extended strip?
      return facing_point.x >= get_top_left_x() &&
          facing_point.x < get_top_left_x() + get_width();
    }
    else {
      // Are we inside the strip and the bounding box?
      return overlaps(facing_point.x, facing_point.y - 8)
          && overlaps(facing_point.x, facing_point.y + 7);
    }
  }
  else {
    // Same thing for a vertical jump.
    if (extended_region) {
      // Are we inside the extended strip?
      return facing_point.y >= get_top_left_y() &&
          facing_point.y < get_top_left_y() + get_height();
    }
    else {
      return overlaps(facing_point.x - 8, facing_point.y) &&
          overlaps(facing_point.x + 7, facing_point.y);
    }
  }
}