/** * \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()); }
/** * \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; }
/** * \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); }
/** * \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; }
/** * \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 }
/** * \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); }
/** * \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"); }
/** * \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 + "'"); } }
/** * \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); }
/** * \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)); }