Exemplo n.º 1
0
/**
 * \brief Returns whether a rectangle overlaps the active region of the jumper.
 *
 * For a horizontal or vertical jumper, the active region is the whole
 * bounding box, that is, an 8-pixel thick horizontal or vertical strip.
 * For a diagonal jumper, the active region is an 8-pixel thick diagonal strip.
 *
 * \param rectangle A rectangle.
 * \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 rectangle overlaps the active region of the jumper.
 */
bool Jumper::overlaps_jumping_region(const Rectangle& rectangle, bool /* extended_region */) const {

  if (!is_jump_diagonal()) {
    return overlaps(rectangle);
  }

  // Check the 4 corners of the rectangle.
  Point xy = rectangle.get_xy();
  if (is_point_in_diagonal(xy)) {
    return true;
  }

  xy.x += rectangle.get_width() - 1;
  if (is_point_in_diagonal(xy)) {
    return true;
  }

  xy.y += rectangle.get_height() - 1;
  if (is_point_in_diagonal(xy)) {
    return true;
  }

  xy.x = rectangle.get_x();
  if (is_point_in_diagonal(xy)) {
    return true;
  }

  // Check the two ends of the diagonal.
  if (get_direction() == 1 || get_direction() == 5) {
    if (rectangle.contains(get_top_left_x(), get_top_left_y())) {
      return true;
    }
    if (rectangle.contains(
        get_top_left_x() + get_width() - 1,
        get_top_left_y() + get_height() - 1)) {
      return true;
    }
  }
  else {
    if (rectangle.contains(
        get_top_left_x() + get_width() - 1, get_top_left_y())) {
      return true;
    }
    if (rectangle.contains(
        get_top_left_x(), get_top_left_y() + get_height() - 1)) {
      return true;
    }
  }

  return false;
}
Exemplo n.º 2
0
/**
 * \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);
}
Exemplo n.º 3
0
/**
 * \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));
}
Exemplo n.º 4
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);
    }
  }
}