Пример #1
0
/**
 * \brief Returns the ground at the specified point.
 *
 * Static tiles and dynamic entities are all taken into account here.
 *
 * \param layer Layer of the point.
 * \param x X coordinate of the point.
 * \param y Y coordinate of the point.
 * \return The ground at this place.
 */
Ground Map::get_ground(Layer layer, int x, int y) const {

  if (test_collision_with_border(x, y)) {
    // Outside the map bounds.
    return Ground::EMPTY;
  }

  // See if a dynamic entity changes the ground.
  // TODO store ground modifiers in a quad tree for performance.

  const std::list<Entity*>& ground_modifiers =
      entities->get_ground_modifiers(layer);
  std::list<Entity*>::const_reverse_iterator it;
  const std::list<Entity*>::const_reverse_iterator rend =
      ground_modifiers.rend();
  for (it = ground_modifiers.rbegin(); it != rend; ++it) {
    const Entity& ground_modifier = *(*it);
    if (ground_modifier.overlaps(x, y)
        && ground_modifier.get_modified_ground() != Ground::EMPTY
        && ground_modifier.is_enabled()
        && !ground_modifier.is_being_removed()) {
      return ground_modifier.get_modified_ground();
    }
  }

  // Otherwise, return the ground defined by static tiles (this is very fast).
  return entities->get_tile_ground(layer, x, y);
}
Пример #2
0
/**
 * \brief Returns the ground at the specified point.
 *
 * Static tiles and dynamic entities are all taken into account here.
 *
 * \param layer Layer of the point.
 * \param x X coordinate of the point.
 * \param y Y coordinate of the point.
 * \return The ground at this place.
 */
Ground Map::get_ground(int layer, int x, int y) const {

  if (test_collision_with_border(x, y)) {
    // Outside the map bounds.
    return Ground::EMPTY;
  }

  // See if a dynamic entity changes the ground.
  const Rectangle box(Point(x, y), Size(1, 1));
  std::vector<EntityPtr> entities_nearby;
  get_entities().get_entities_in_rectangle_sorted(box, entities_nearby);

  const auto& rend = entities_nearby.rend();
  for (auto it = entities_nearby.rbegin(); it != rend; ++it) {
    const Entity& entity_nearby = *(*it);

    const Ground ground = entity_nearby.get_modified_ground();
    if (ground == Ground::EMPTY) {
      // The entity has no influence on the ground.
      continue;
    }

    if (entity_nearby.overlaps(x, y) &&
        entity_nearby.get_layer() == layer &&
        entity_nearby.is_enabled() &&
        !entity_nearby.is_being_removed()
    ) {
      return entity_nearby.get_modified_ground();
    }
  }

  // Otherwise, return the ground defined by static tiles (this is very fast).
  return entities->get_tile_ground(layer, x, y);
}
Пример #3
0
/**
 * \brief Tests whether a point collides with the ground of the map.
 *
 * The ground is the terrain of the point. It is defined by the tiles and
 * by the presence of entities that may change it
 * (like dynamic tiles and destructible items).
 *
 * This method also returns true if the point is outside the map.
 *
 * \param layer Layer of the point.
 * \param x X of the point in pixels.
 * \param y Y of the point in pixels.
 * \param entity_to_check The entity to check (used to decide what grounds are
 * considered as obstacle).
 * \param [out] found_diagonal_wall \c true if the ground under this point was
 * a diagonal wall, unchanged otherwise.
 * Your algorithm may decide to check more points if there is a diagonal wall.
 * \return \c true if this point is on an obstacle.
 */
bool Map::test_collision_with_ground(
    Layer layer,
    int x,
    int y,
    const MapEntity& entity_to_check,
    bool& found_diagonal_wall) const {

  bool on_obstacle = false;
  int x_in_tile, y_in_tile;

  // If the point is outside the map, this is an obstacle.
  if (test_collision_with_border(x, y)) {
    return true;
  }

  // Get the ground property under this point.
  Ground ground = get_ground(layer, x, y);
  switch (ground) {

  case GROUND_EMPTY:
  case GROUND_TRAVERSABLE:
  case GROUND_GRASS:
  case GROUND_ICE:
    // The square is not an obstacle.
    on_obstacle = false;
    break;

  case GROUND_WALL:
    // The square is entirely an obstacle.
    on_obstacle = true;
    break;

  case GROUND_WALL_TOP_RIGHT:
  case GROUND_WALL_TOP_RIGHT_WATER:
    // The upper right half of the square is an obstacle
    // so we have to test the position of the point in the square.
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile <= x_in_tile;
    found_diagonal_wall = true;
    break;

  case GROUND_WALL_TOP_LEFT:
  case GROUND_WALL_TOP_LEFT_WATER:
    // Same thing.
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile <= 7 - x_in_tile;
    found_diagonal_wall = true;
    break;

  case GROUND_WALL_BOTTOM_LEFT:
  case GROUND_WALL_BOTTOM_LEFT_WATER:
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile >= x_in_tile;
    found_diagonal_wall = true;
    break;

  case GROUND_WALL_BOTTOM_RIGHT:
  case GROUND_WALL_BOTTOM_RIGHT_WATER:
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile >= 7 - x_in_tile;
    found_diagonal_wall = true;
    break;

  case GROUND_LOW_WALL:
    on_obstacle = entity_to_check.is_low_wall_obstacle();
    break;

  case GROUND_SHALLOW_WATER:
    on_obstacle = entity_to_check.is_shallow_water_obstacle();
    break;

  case GROUND_DEEP_WATER:
    on_obstacle = entity_to_check.is_deep_water_obstacle();
    break;

  case GROUND_HOLE:
    on_obstacle = entity_to_check.is_hole_obstacle();
    break;

  case GROUND_LAVA:
    on_obstacle = entity_to_check.is_lava_obstacle();
    break;

  case GROUND_PRICKLE:
    on_obstacle = entity_to_check.is_prickle_obstacle();
    break;

  case GROUND_LADDER:
    on_obstacle = entity_to_check.is_ladder_obstacle();
    break;
  }

  return on_obstacle;
}
Пример #4
0
/**
 * \brief Tests whether a point collides with the ground of the map.
 *
 * The ground is the terrain of the point. It is defined by the tiles and
 * by the presence of entities that may change it
 * (like dynamic tiles and destructible items).
 *
 * This method also returns true if the point is outside the map.
 *
 * \param layer Layer of the point.
 * \param x X of the point in pixels.
 * \param y Y of the point in pixels.
 * \param entity_to_check The entity to check (used to decide what grounds are
 * considered as obstacle).
 * \param [out] found_diagonal_wall \c true if the ground under this point was
 * a diagonal wall, unchanged otherwise.
 * Your algorithm may decide to check more points if there is a diagonal wall.
 * \return \c true if this point is on an obstacle.
 */
bool Map::test_collision_with_ground(
    int layer,
    int x,
    int y,
    const Entity& entity_to_check,
    bool& found_diagonal_wall) const {

  bool on_obstacle = false;
  int x_in_tile, y_in_tile;

  // If the point is outside the map, this is an obstacle.
  if (test_collision_with_border(x, y)) {
    return true;
  }

  // Get the ground property under this point.
  Ground ground = get_ground(layer, x, y);
  switch (ground) {

  case Ground::EMPTY:
  case Ground::TRAVERSABLE:
  case Ground::GRASS:
  case Ground::ICE:
    // The square is not an obstacle.
    on_obstacle = false;
    break;

  case Ground::WALL:
    // The square is entirely an obstacle.
    on_obstacle = true;
    break;

  case Ground::WALL_TOP_RIGHT:
  case Ground::WALL_TOP_RIGHT_WATER:
    // The upper right half of the square is an obstacle
    // so we have to test the position of the point in the square.
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile <= x_in_tile;
    found_diagonal_wall = true;
    break;

  case Ground::WALL_TOP_LEFT:
  case Ground::WALL_TOP_LEFT_WATER:
    // Same thing.
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile <= 7 - x_in_tile;
    found_diagonal_wall = true;
    break;

  case Ground::WALL_BOTTOM_LEFT:
  case Ground::WALL_BOTTOM_LEFT_WATER:
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile >= x_in_tile;
    found_diagonal_wall = true;
    break;

  case Ground::WALL_BOTTOM_RIGHT:
  case Ground::WALL_BOTTOM_RIGHT_WATER:
    x_in_tile = x & 7;
    y_in_tile = y & 7;
    on_obstacle = y_in_tile >= 7 - x_in_tile;
    found_diagonal_wall = true;
    break;

  case Ground::LOW_WALL:
  case Ground::SHALLOW_WATER:
  case Ground::DEEP_WATER:
  case Ground::HOLE:
  case Ground::LAVA:
  case Ground::PRICKLE:
  case Ground::LADDER:
    on_obstacle = entity_to_check.is_ground_obstacle(ground);
    break;
  }

  return on_obstacle;
}