Beispiel #1
0
/**
 * \brief Creates a new chest with the specified treasure.
 * \param name Name identifying this chest.
 * \param layer Layer of the chest to create on the map.
 * \param xy Coordinates of the chest to create.
 * \param sprite_name Name of the animation set of the
 * sprite to create for the chest. It must have animations "open" and "closed".
 * \param treasure The treasure in the chest.
 */
Chest::Chest(
    const std::string& name,
    Layer layer,
    const Point& xy,
    const std::string& sprite_name,
    const Treasure& treasure):

  Detector(COLLISION_FACING, name, layer, xy, Size(16, 16)),
  treasure(treasure),
  open(treasure.is_found()),
  treasure_given(open),
  treasure_date(0),
  opening_method(OpeningMethod::BY_INTERACTION),
  opening_condition_consumed(false) {

  // Create the sprite.
  Sprite& sprite = *create_sprite(sprite_name);
  std::string animation = is_open() ? "open" : "closed";
  sprite.set_current_animation(animation);

  set_origin(get_width() / 2, get_height() - 3);

  // TODO set this as the default drawn_in_y_order for MapEntity
  set_drawn_in_y_order(sprite.get_max_size().height > get_height());
}
Beispiel #2
0
/**
 * \brief Creates an arrow.
 * \param hero The hero.
 */
Arrow::Arrow(const Hero& hero):
  MapEntity("", 0, hero.get_layer(), 0, 0, 0, 0),
  hero(hero) {

  // initialize the entity
  int direction = hero.get_animation_direction();
  create_sprite("entities/arrow", true);
  get_sprite().set_current_direction(direction);
  set_drawn_in_y_order(true);

  if (direction % 2 == 0) {
    // Horizontal.
    set_size(16, 8);
    set_origin(8, 4);
  }
  else {
    // Vertical.
    set_size(8, 16);
    set_origin(4, 8);
  }

  set_xy(hero.get_center_point());
  set_optimization_distance(0); // Make the arrow continue outside the screen until disappear_date.

  std::string path = " ";
  path[0] = '0' + (direction * 2);
  Movement* movement = new PathMovement(path, 192, true, false, false);
  set_movement(movement);

  disappear_date = System::now() + 10000;
  stop_now = false;
  entity_reached = NULL;
}
Beispiel #3
0
/**
 * \brief Creates a block.
 * \param name name identifying this block
 * \param layer layer of the entity to create
 * \param xy Coordinate of the entity to create.
 * \param direction the only direction where the block can be moved
 * or -1 to allow it to be pushed in any direction
 * \param sprite_name animation set id of the sprite for this block
 * \param can_be_pushed true to allow the hero to push this block
 * \param can_be_pulled true to allow the hero to pull this block
 * \param maximum_moves indicates how many times the block can
 * be moved (0: none, 1: once, 2: infinite)
 */
Block::Block(
    const std::string& name,
    int layer,
    const Point& xy,
    int direction,
    const std::string& sprite_name,
    bool can_be_pushed,
    bool can_be_pulled,
    int maximum_moves
):
  Entity(name, direction, layer, xy, Size(16, 16)),
  maximum_moves(maximum_moves),
  sound_played(false),
  when_can_move(System::now()),
  last_position(xy),
  initial_position(xy),
  initial_maximum_moves(maximum_moves),
  can_be_pushed(can_be_pushed),
  can_be_pulled(can_be_pulled) {

  Debug::check_assertion(maximum_moves >= 0 && maximum_moves <= 2,
      "maximum_moves must be between 0 and 2");

  set_collision_modes(CollisionMode::COLLISION_FACING);
  set_origin(8, 13);
  set_direction(direction);
  const SpritePtr& sprite = create_sprite(sprite_name);
  set_drawn_in_y_order(sprite->get_size().height > 16);
}
Beispiel #4
0
/**
 * \brief Creates an arrow.
 * \param hero The hero.
 */
Arrow::Arrow(const Hero& hero):
  Entity("", 0, hero.get_layer(), Point(0, 0), Size(0, 0)),
  hero(hero) {

  // initialize the entity
  int direction = hero.get_animation_direction();
  create_sprite("entities/arrow", true);
  get_sprite().set_current_direction(direction);
  set_drawn_in_y_order(true);

  if (direction % 2 == 0) {
    // Horizontal.
    set_size(16, 8);
    set_origin(8, 4);
  }
  else {
    // Vertical.
    set_size(8, 16);
    set_origin(4, 8);
  }

  set_xy(hero.get_center_point());
  notify_position_changed();

  std::string path = " ";
  path[0] = '0' + (direction * 2);
  set_movement(std::make_shared<PathMovement>(
      path, 192, true, false, false
  ));

  disappear_date = System::now() + 10000;
  stop_now = false;
  entity_reached = nullptr;
}
Beispiel #5
0
/**
 * \brief Constructor.
 *
 * Creates a bomb.
 *
 * \param name Name identifying the entity on the map or an empty string.
 * \param layer layer of the entity to create
 * \param x x coordinate of the entity to create
 * \param y y coordinate of the entity to create
 */
Bomb::Bomb(const std::string& name, Layer layer, int x, int y):
  Detector(COLLISION_FACING, name, layer, x, y, 16, 16),
  explosion_date(System::now() + 6000) {

  create_sprite("entities/bomb");
  get_sprite().enable_pixel_collisions();
  set_size(16, 16);
  set_origin(8, 13);
  set_drawn_in_y_order(true);
  set_optimization_distance(0); // make the bomb explode even if the hero runs far away
}
Beispiel #6
0
/**
 * \brief Constructor.
 *
 * Creates a bomb.
 *
 * \param name Name identifying the entity on the map or an empty string.
 * \param layer layer of the entity to create
 * \param xy Coordinates of the entity to create.
 */
Bomb::Bomb(const std::string& name, int layer, const Point& xy):
  Entity(name, 0, layer, xy, Size(16, 16)),
  explosion_date(System::now() + 6000) {

  set_collision_modes(CollisionMode::COLLISION_FACING);
  const SpritePtr& sprite = create_sprite("entities/bomb");
  sprite->enable_pixel_collisions();
  set_size(16, 16);
  set_origin(8, 13);
  set_drawn_in_y_order(true);
}
Beispiel #7
0
/**
 * \brief Creates a carried item (i.e. an item carried by the hero).
 * \param hero the hero who is lifting the item to be created
 * \param original_entity the entity that will be replaced by this carried item
 * (its coordinates, size and origin will be copied)
 * \param animation_set_id name of the animation set for the sprite to create
 * \param destruction_sound_id Name of the sound to play when this item is destroyed
 * (or an empty string).
 * \param damage_on_enemies damage received by an enemy if the item is thrown on him
 * (possibly 0)
 * \param explosion_date date of the explosion if the item should explode,
 * or 0 if the item does not explode
 */
CarriedItem::CarriedItem(
    Hero& hero,
    const Entity& original_entity,
    const std::string& animation_set_id,
    const std::string& destruction_sound_id,
    int damage_on_enemies,
    uint32_t explosion_date
):
  Entity("", 0, hero.get_layer(), Point(0, 0), Size(0, 0)),
  hero(hero),
  is_lifting(true),
  is_throwing(false),
  is_breaking(false),
  break_one_layer_above(false),
  destruction_sound_id(destruction_sound_id),
  damage_on_enemies(damage_on_enemies),
  shadow_sprite(nullptr),
  throwing_direction(0),
  next_down_date(0),
  item_height(0),
  y_increment(0),
  explosion_date(explosion_date) {

  // align correctly the item with the hero
  int direction = hero.get_animation_direction();
  if (direction % 2 == 0) {
    set_xy(original_entity.get_x(), hero.get_y());
  }
  else {
    set_xy(hero.get_x(), original_entity.get_y());
  }
  set_origin(original_entity.get_origin());
  set_size(original_entity.get_size());
  set_drawn_in_y_order(true);

  // create the lift movement and the sprite
  std::shared_ptr<PixelMovement> movement = std::make_shared<PixelMovement>(
      lifting_trajectories[direction], 100, false, true
  );
  create_sprite(animation_set_id);
  get_sprite().set_current_animation("stopped");
  set_movement(movement);

  // create the shadow (not visible yet)
  shadow_sprite = std::make_shared<Sprite>("entities/shadow");
  shadow_sprite->set_current_animation("big");
}
Beispiel #8
0
/**
 * \brief Creates an NPC.
 * \param game the game
 * \param name name identifying this NPC
 * \param layer layer of the entity to create
 * \param xy Coordinates of the entity to create.
 * \param subtype the subtype of interaction
 * \param sprite_name sprite animation set of the entity, or an empty string to create no sprite
 * \param direction for a generalized NPC: direction for which the interactions are allowed
 * (0 to 4, or -1 for any direction), for a usual NPC: initial direction of the NPC's sprite
 * \param behavior_string indicates what happens when the hero interacts with this NPC:
 * "dialog#XXX" to start the dialog XXX, "map" to call the map script
 * (with an event_hero_interaction() call) or "item#XXX" to call the script
 * of item XXX  (with an event_hero_interaction() call)
 */
Npc::Npc(
    Game& /* game */,
    const std::string& name,
    int layer,
    const Point& xy,
    Subtype subtype,
    const std::string& sprite_name,
    int direction,
    const std::string& behavior_string
):
  Entity(name, 0, layer, xy, Size(0, 0)),
  subtype(subtype),
  behavior(BEHAVIOR_MAP_SCRIPT),
  traversable(false),
  dialog_to_show(""),
  item_name("") {

  set_collision_modes(CollisionMode::COLLISION_FACING | CollisionMode::COLLISION_OVERLAPPING);
  initialize_sprite(sprite_name, direction);
  set_size(16, 16);
  set_origin(8, 13);
  set_direction(direction);

  // Usual NPCs are displayed like the hero whereas generalized NPCs are
  // not necessarily people.
  set_drawn_in_y_order(subtype == USUAL_NPC);

  // behavior
  if (behavior_string == "map") {
    behavior = BEHAVIOR_MAP_SCRIPT;
  }
  else if (behavior_string.substr(0, 5) == "item#") {
    behavior = BEHAVIOR_ITEM_SCRIPT;
    item_name = behavior_string.substr(5);
  }
  else if (behavior_string.substr(0, 7) == "dialog#") {
    behavior = BEHAVIOR_DIALOG;
    dialog_to_show = behavior_string.substr(7);
  }
  else {
    Debug::die(std::string("Invalid behavior string for NPC '") + name
        + "': '" + behavior_string + "'");
  }
}
Beispiel #9
0
/**
 * \brief Creates an enemy.
 * \param game The game.
 * \param name Name identifying the enemy or an empty string.
 * \param layer The layer on the map.
 * \param x X position on the map.
 * \param y Y position on the map.
 * \param breed Breed of the enemy.
 * \param treasure Treasure dropped when the enemy is killed.
 */
Enemy::Enemy(
    Game& game,
    const std::string& name,
    Layer layer,
    int x,
    int y,
    const std::string& breed,
    const Treasure& treasure):

  Detector(COLLISION_OVERLAPPING | COLLISION_SPRITE,
      name, layer, x, y, 0, 0),

  breed(breed),
  damage_on_hero(1),
  life(1),
  hurt_style(HURT_NORMAL),
  pushed_back_when_hurt(true),
  push_hero_on_sword(false),
  can_hurt_hero_running(false),
  minimum_shield_needed(0),
  rank(RANK_NORMAL),
  savegame_variable(),
  traversable(true),
  obstacle_behavior(OBSTACLE_BEHAVIOR_NORMAL),
  being_hurt(false),
  stop_hurt_date(0),
  invulnerable(false),
  vulnerable_again_date(0),
  can_attack(true),
  can_attack_again_date(0),
  immobilized(false),
  start_shaking_date(0),
  end_shaking_date(0),
  dying_animation_started(false),
  treasure(treasure),
  exploding(false),
  nb_explosions(0),
  next_explosion_date(0) {

  set_size(16, 16);
  set_origin(8, 13);
  set_drawn_in_y_order(true);
}
Beispiel #10
0
/**
 * \brief Creates a hookshot.
 * \param hero the hero
 */
Hookshot::Hookshot(const Hero& hero):
    MapEntity("", 0, hero.get_layer(), 0, 0, 0, 0),
    next_sound_date(System::now()),
    has_to_go_back(false),
    going_back(false),
    entity_reached(nullptr),
    link_sprite(std::make_shared<Sprite>("entities/hookshot")) {

  // initialize the entity
  int direction = hero.get_animation_direction();
  create_sprite("entities/hookshot", true);
  get_sprite().set_current_direction(direction);
  link_sprite->set_current_animation("link");

  set_size(16, 16);
  set_origin(8, 13);
  set_drawn_in_y_order(true);
  set_xy(hero.get_xy());

  std::string path = " ";
  path[0] = '0' + (direction * 2);
  set_movement(std::make_shared<PathMovement>(path, 192, true, false, false));
}