/** * \brief This function is called by the engine when an entity overlaps the pickable item. * * If the entity is the player, we give him the item, and the map is notified * to destroy it. * \param entity_overlapping the entity overlapping the detector * \param collision_mode the collision mode that detected the collision */ void Pickable::notify_collision(MapEntity& entity_overlapping, CollisionMode /* collision_mode */) { if (entity_overlapping.is_hero()) { try_give_item_to_player(); } else if (entity_followed == nullptr) { MapEntityPtr shared_entity_overlapping = std::static_pointer_cast<MapEntity>(entity_overlapping.shared_from_this()); if (entity_overlapping.get_type() == ENTITY_BOOMERANG) { Boomerang& boomerang = static_cast<Boomerang&>(entity_overlapping); if (!boomerang.is_going_back()) { boomerang.go_back(); } entity_followed = shared_entity_overlapping; } else if (entity_overlapping.get_type() == ENTITY_HOOKSHOT) { Hookshot& hookshot = static_cast<Hookshot&>(entity_overlapping); if (!hookshot.is_going_back()) { hookshot.go_back(); } entity_followed = shared_entity_overlapping; } if (entity_followed != nullptr) { clear_movement(); set_movement(std::make_shared<FollowMovement>( entity_followed, 0, 0, true )); falling_height = FALLING_NONE; set_blinking(false); } } }
/** * \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 This function is called when the player tries to push or pull this block. * @return true if the player is allowed to move this block */ bool Block::start_movement_by_hero() { Hero& hero = get_hero(); bool pulling = hero.is_grabbing_or_pulling(); int allowed_direction = get_direction(); int hero_direction = hero.get_animation_direction(); if (pulling) { // the movement direction is backwards hero_direction = (hero_direction + 2) % 4; } if (get_movement() != NULL // the block is already moving || maximum_moves == 0 // the block cannot move anymore || System::now() < when_can_move // the block cannot move for a while || (pulling && !can_be_pulled) // the hero tries to pull a block that cannot be pulled || (!pulling && !can_be_pushed) // the hero tries to push a block that cannot be pushed || (allowed_direction != -1 && hero_direction != allowed_direction)) { // incorrect direction return false; } int dx = get_x() - hero.get_x(); int dy = get_y() - hero.get_y(); set_movement(new FollowMovement(&hero, dx, dy, false)); sound_played = false; return true; }
/** * \brief Hurts the enemy. * * Updates its state, its sprite and plays the sound. * * \param source the entity attacking the enemy (often the hero) */ void Enemy::hurt(MapEntity& source) { uint32_t now = System::now(); // update the enemy state being_hurt = true; set_movement_events_enabled(false); can_attack = false; can_attack_again_date = now + 300; // graphics and sounds set_animation("hurt"); play_hurt_sound(); // stop any movement clear_movement(); // push the enemy back if (pushed_back_when_hurt) { double angle = source.get_angle(*this); StraightMovement* movement = new StraightMovement(false, true); movement->set_max_distance(24); movement->set_speed(120); movement->set_angle(angle); set_movement(movement); } stop_hurt_date = now + 300; }
/** * \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 Throws the item. * \param direction direction where the hero throws the item (0 to 3) */ void CarriedItem::throw_item(int direction) { this->throwing_direction = direction; this->is_lifting = false; this->is_throwing = true; // play the sound Sound::play("throw"); // stop the sprite animation Sprite& sprite = get_sprite(); sprite.set_current_animation("stopped"); // set the movement of the item sprite set_y(hero.get_y()); std::shared_ptr<StraightMovement> movement = std::make_shared<StraightMovement>(false, false); movement->set_speed(200); movement->set_angle(Geometry::degrees_to_radians(direction * 90)); clear_movement(); set_movement(movement); this->y_increment = -2; this->next_down_date = System::now() + 40; this->item_height = 18; }
/** * \brief This function is called by the engine when an entity overlaps the pickable item. * * If the entity is the player, we give him the item, and the map is notified * to destroy it. * \param entity_overlapping the entity overlapping the detector * \param collision_mode the collision mode that detected the collision */ void Pickable::notify_collision(MapEntity& entity_overlapping, CollisionMode collision_mode) { if (entity_overlapping.is_hero()) { try_give_item_to_player(); } else if (entity_followed == NULL) { if (entity_overlapping.get_type() == ENTITY_BOOMERANG) { Boomerang& boomerang = static_cast<Boomerang&>(entity_overlapping); if (!boomerang.is_going_back()) { boomerang.go_back(); } entity_followed = &boomerang; } else if (entity_overlapping.get_type() == ENTITY_HOOKSHOT) { Hookshot& hookshot = static_cast<Hookshot&>(entity_overlapping); if (!hookshot.is_going_back()) { hookshot.go_back(); } entity_followed = &hookshot; } if (entity_followed != NULL) { clear_movement(); set_movement(new FollowMovement(entity_followed, 0, 0, true)); falling_height = FALLING_NONE; set_blinking(false); } } }
/** * @brief Updates this entity. */ void Hookshot::update() { MapEntity::update(); if (suspended) { return; } uint32_t now = System::now(); if (now >= next_sound_date) { Sound::play("hookshot"); next_sound_date = now + 150; } if (entity_reached == NULL) { if (!going_back) { if (has_to_go_back) { going_back = true; Movement *movement = new TargetMovement(&get_hero(), 192, true); clear_movement(); set_movement(movement); } else if (get_distance(get_hero()) >= 120) { go_back(); } } else if (get_distance(get_hero()) == 0 || (get_movement() != NULL && get_movement()->is_finished())) { remove_from_map(); get_hero().start_state_from_ground(); } } }
void Player::walk_right() { _walk_right->increment_frame(); apply_movement(_walk, 0); if (_movement.x >_max_walk) set_movement(_max_walk, _movement.y); _facing_right = true; set_state(ENTITY_WALKING); }
void Player::walk_left() { _walk_left->increment_frame(); apply_movement(-_walk, 0); if (_movement.x < -_max_walk) set_movement(-_max_walk, _movement.y); _facing_right = false; set_state(ENTITY_WALKING); }
void Player::stop_walking() { //Decelerate if (_state == ENTITY_WALKING) { if (_movement.x < 0) { apply_movement(_walk_stop, 0); if (_movement.x > 0) set_movement(0, _movement.y); } else if (_movement.x > 0) { apply_movement(-_walk_stop, 0); if (_movement.x < 0) set_movement(0, _movement.y); } if (round(_movement.x) == 0.f) { set_movement(0.f, _movement.y); unset_state(ENTITY_WALKING); } } }
/** * \brief Creates a boomerang. * \param hero the hero * \param max_distance maximum distance of the movement in pixels * \param speed speed of the movement in pixels per second * \param angle the angle of the boomerang trajectory in radians * \param sprite_name animation set id representing the boomerang */ Boomerang::Boomerang( Hero& hero, int max_distance, int speed, double angle, const std::string& sprite_name): MapEntity("", 0, hero.get_layer(), 0, 0, 0, 0), hero(hero), has_to_go_back(false), going_back(false), speed(speed) { // initialize the entity create_sprite(sprite_name); set_size(16, 16); set_origin(8, 8); int hero_x = hero.get_top_left_x(); int hero_y = hero.get_top_left_y(); switch (hero.get_animation_direction()) { case 0: set_xy(hero_x + 24, hero_y + 8); break; case 1: set_xy(hero_x + 8, hero_y - 8); break; case 2: set_xy(hero_x - 8, hero_y + 8); break; case 3: set_xy(hero_x + 8, hero_y + 24); break; } initial_coords.set_xy(get_xy()); StraightMovement* movement = new StraightMovement(false, false); movement->set_speed(speed); movement->set_angle(angle); movement->set_max_distance(max_distance); set_movement(movement); next_sound_date = System::now(); }
/** * \brief Creates a boomerang. * \param hero the hero * \param max_distance maximum distance of the movement in pixels * \param speed speed of the movement in pixels per second * \param angle the angle of the boomerang trajectory in radians * \param sprite_name animation set id representing the boomerang */ Boomerang::Boomerang( const HeroPtr& hero, int max_distance, int speed, double angle, const std::string& sprite_name ): Entity("", 0, hero->get_layer(), Point(0, 0), Size(0, 0)), hero(hero), has_to_go_back(false), going_back(false), speed(speed) { // initialize the entity create_sprite(sprite_name); set_size(16, 16); set_origin(8, 8); int hero_x = hero->get_top_left_x(); int hero_y = hero->get_top_left_y(); switch (hero->get_animation_direction()) { case 0: set_xy(hero_x + 24, hero_y + 8); break; case 1: set_xy(hero_x + 8, hero_y - 8); break; case 2: set_xy(hero_x - 8, hero_y + 8); break; case 3: set_xy(hero_x + 8, hero_y + 24); break; } std::shared_ptr<StraightMovement> movement = std::make_shared<StraightMovement>(false, false); movement->set_speed(speed); movement->set_angle(angle); movement->set_max_distance(max_distance); set_movement(movement); next_sound_date = System::now(); }
/** * \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 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, MapEntity& original_entity, const std::string& animation_set_id, const std::string& destruction_sound_id, int damage_on_enemies, uint32_t explosion_date): MapEntity(), hero(hero), is_lifting(true), is_throwing(false), is_breaking(false), break_on_intermediate_layer(false) { // put the item on the hero's layer set_layer(hero.get_layer()); // 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()); // create the lift movement and the sprite PixelMovement *movement = new PixelMovement(lifting_trajectories[direction], 100, false, true); create_sprite(animation_set_id); get_sprite().set_current_animation("stopped"); set_movement(movement); // create the breaking sound this->destruction_sound_id = destruction_sound_id; // create the shadow (not visible yet) this->shadow_sprite = new Sprite("entities/shadow"); this->shadow_sprite->set_current_animation("big"); // damage on enemies this->damage_on_enemies = damage_on_enemies; // explosion this->explosion_date = explosion_date; }
void state_find_track_go_a_bit_more_control_logic() { if (state_find_track_go_a_bit_more_control_data.not_first_run == false){ state_find_track_go_a_bit_more_control_data.not_first_run = true; task_t system_state = {.data.command = STATE_COMMAND, .data.timestamp=0, .data.value=STATE_FIND_GO_A_BIT_MORE}; add_task(&system_state); set_m_forward(); l_motor.rpm = 0; r_motor.rpm = 0; //set_movement(0x32,C_FIND_BIT_MORE,BACKWARD); set_movement(0x32,C90,LEFT); } if (l_motor.corner==C0 && r_motor.corner==C0) { state_find_track_turn_left_control_data.not_first_run=false; set_state(state_find_track_turn_left_control_logic); } }
/** * \brief This function is called when a conveyor belt detects a collision with this entity. * \param conveyor_belt a conveyor belt * \param dx direction of the x move in pixels (0, 1 or -1) * \param dy direction of the y move in pixels (0, 1 or -1) */ void Bomb::notify_collision_with_conveyor_belt(ConveyorBelt& conveyor_belt, int dx, int dy) { if (get_movement() == NULL) { // check that a significant part of the bomb is on the conveyor belt Rectangle center = get_center_point(); center.add_xy(-1, -1); center.set_size(2, 2); if (conveyor_belt.overlaps(center)) { set_xy(conveyor_belt.get_xy()); std::string path = " "; path[0] = path[1] = '0' + conveyor_belt.get_direction(); clear_movement(); set_movement(new PathMovement(path, 64, false, false, false)); } } }
void Controller::run() { Uint32 ref_time = SDL_GetTicks(); while(running) { SDL_Event e; while(SDL_PollEvent(&e)) { handle_event(&e); } Uint32 now = SDL_GetTicks(); if(now - ref_time > 10) { set_movement(); running = game.tick(); game_view->update(); render_display(); ref_time = now; } } }
/** * \brief Creates an arrow. * \param hero the hero */ Arrow::Arrow(Hero& hero): hero(hero) { // initialize the entity int direction = hero.get_animation_direction(); set_layer(hero.get_layer()); create_sprite("entities/arrow", true); get_sprite().set_current_direction(direction); set_bounding_box_from_sprite(); 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; }
/** * \copydoc MapEntity::notify_collision_with_stream */ void Bomb::notify_collision_with_stream(Stream& stream, int /* dx */, int /* dy */) { if (get_movement() == nullptr) { // TODO use a StreamAction, since it now works with any entity and not only the hero. // Check that a significant part of the bomb is on the stream. Rectangle center(get_center_point(), Size(2, 2)); center.add_xy(-1, -1); if (stream.overlaps(center)) { set_xy(stream.get_xy()); std::string path = " "; path[0] = path[1] = '0' + stream.get_direction(); clear_movement(); set_movement(std::make_shared<PathMovement>( path, 64, false, false, false )); } } }
/** * \brief Updates the boomerang. */ void Boomerang::update() { MapEntity::update(); if (is_suspended()) { return; } uint32_t now = System::now(); if (now >= next_sound_date) { Sound::play("boomerang"); next_sound_date = now + 150; } if (!going_back && has_to_go_back) { going_back = true; clear_movement(); set_movement(new TargetMovement(&hero, 0, 0, speed, true)); get_entities().set_entity_layer(*this, hero.get_layer()); // because the hero's layer may have changed } }
/** * \brief Updates this entity. */ void Hookshot::update() { MapEntity::update(); if (is_suspended()) { return; } uint32_t now = System::now(); if (now >= next_sound_date) { Sound::play("hookshot"); next_sound_date = now + 150; } if (entity_reached == nullptr) { if (!going_back) { if (has_to_go_back) { going_back = true; std::shared_ptr<Movement> movement = std::make_shared<TargetMovement>( std::static_pointer_cast<Hero>(get_hero().shared_from_this()), 0, 0, 192, true ); clear_movement(); set_movement(movement); } else if (get_distance(get_hero()) >= 120) { go_back(); } } else if (get_distance(get_hero()) == 0 || (get_movement() != nullptr && get_movement()->is_finished())) { remove_from_map(); get_hero().start_state_from_ground(); } } }
/** * \brief Wrapper around set_corner function to be used with the usart interface * * \param task Used to specify a pointer to a specific received task. * * \return void */ void set_movement_task(task_t *task) { static corner_t temp_corner= C0; switch (task->data.u8[2]) { case 0: temp_corner = C0; break; case 1: temp_corner = C45; break; case 2: temp_corner = C90; break; case 3: temp_corner = C_FIND_BIT_MORE; break; default: temp_corner = C0; break; } set_movement(task->data.u8[3],temp_corner,task->data.u8[1]); }
/** * @brief Creates a hookshot. * @param hero the hero */ Hookshot::Hookshot(Hero &hero): next_sound_date(System::now()), has_to_go_back(false), going_back(false), entity_reached(NULL), link_sprite("entities/hookshot") { // initialize the entity int direction = hero.get_animation_direction(); set_layer(hero.get_layer()); 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_xy(hero.get_xy()); std::string path = " "; path[0] = '0' + (direction * 2); Movement *movement = new PathMovement(path, 192, true, false, false); set_movement(movement); }
/** * \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)); }
/** * \brief Initializes the movement of the item (if it is falling), * depending on its subtype. */ void Pickable::initialize_movement() { if (is_falling()) { set_movement(std::make_shared<FallingOnFloorMovement>(falling_height)); } }
/** * \brief This function is called repeatedly. */ void CarriedItem::update() { // update the sprite and the position Entity::update(); if (is_suspended()) { return; } // when the hero finishes lifting the item, start carrying it if (is_lifting && get_movement()->is_finished()) { is_lifting = false; // make the item follow the hero clear_movement(); set_movement(std::make_shared<RelativeMovement>( std::static_pointer_cast<Hero>(hero.shared_from_this()), 0, -18, true )); } // when the item has finished flying, destroy it else if (can_explode() && !is_breaking) { uint32_t now = System::now(); if (now >= explosion_date) { break_item(); } else if (will_explode_soon()) { std::string animation = get_sprite().get_current_animation(); if (animation == "stopped") { get_sprite().set_current_animation("stopped_explosion_soon"); } else if (animation == "walking") { get_sprite().set_current_animation("walking_explosion_soon"); } } } if (is_broken()) { remove_from_map(); } else if (is_throwing) { shadow_sprite->update(); if (break_one_layer_above) { break_item(); int layer = get_layer(); if (layer != get_map().get_highest_layer()) { get_entities().set_entity_layer(*this, layer + 1); } break_one_layer_above = false; } else if (get_movement()->is_stopped() || y_increment >= 7) { // Interrupt the movement. break_item_on_ground(); } else { uint32_t now = System::now(); while (now >= next_down_date) { next_down_date += 40; item_height -= y_increment; y_increment++; } } } }
/** * \brief Updates this entity. */ void Arrow::update() { MapEntity::update(); if (is_suspended()) { return; } uint32_t now = System::now(); // stop the movement if necessary (i.e. stop() was called) if (stop_now) { clear_movement(); stop_now = false; if (entity_reached != NULL) { // the arrow just hit an entity (typically an enemy) and this entity may have a movement Rectangle dxy(get_x() - entity_reached->get_x(), get_y() - entity_reached->get_y()); set_movement(new FollowMovement(entity_reached, dxy.get_x(), dxy.get_y(), true)); } } if (entity_reached != NULL) { // see if the entity reached is still valid if (is_stopped()) { // the arrow is stopped because the entity that was reached just disappeared disappear_date = now; } else if (entity_reached->get_type() == ENTITY_DESTRUCTIBLE && !entity_reached->is_obstacle_for(*this)) { disappear_date = now; } else if (entity_reached->get_type() == ENTITY_ENEMY && ((Enemy*) entity_reached)->is_dying()) { // the enemy is dying disappear_date = now; } } // see if the arrow just hit a wall or an entity bool reached_obstacle = false; if (get_sprite().get_current_animation() != "reached_obstacle") { if (entity_reached != NULL) { // the arrow was just attached to an entity reached_obstacle = true; } else if (is_stopped()) { if (has_reached_map_border()) { // the map border was reached: destroy the arrow disappear_date = now; } else { // the arrow has just hit another obstacle reached_obstacle = true; } } } if (reached_obstacle) { // an obstacle or an entity was just reached disappear_date = now + 1500; get_sprite().set_current_animation("reached_obstacle"); Sound::play("arrow_hit"); if (entity_reached == NULL) { clear_movement(); } check_collision_with_detectors(false); } // destroy the arrow when disappear_date is reached if (now >= disappear_date) { remove_from_map(); } }
/** * @brief This function is called repeatedly. */ void CarriedItem::update() { // update the sprite and the position MapEntity::update(); if (suspended) { return; } // when the hero finishes lifting the item, start carrying it if (is_lifting && get_movement()->is_finished()) { is_lifting = false; // make the item follow the hero clear_movement(); set_movement(new FollowMovement(&hero, 0, -18, true)); } // when the item has finished flying, destroy it else if (can_explode() && !is_breaking) { uint32_t now = System::now(); if (now >= explosion_date) { break_item(); } else if (will_explode_soon()) { std::string animation = get_sprite().get_current_animation(); if (animation == "stopped") { get_sprite().set_current_animation("stopped_explosion_soon"); } else if (animation == "walking") { get_sprite().set_current_animation("walking_explosion_soon"); } } } if (is_throwing) { shadow_sprite->update(); if (is_broken()) { remove_from_map(); } else if (break_on_intermediate_layer) { break_item(); get_entities().set_entity_layer(*this, LAYER_INTERMEDIATE); break_on_intermediate_layer = false; } else if (get_movement()->is_stopped() || y_increment >= 7) { break_item(); } else { uint32_t now = System::now(); while (now >= next_down_date) { next_down_date += 40; item_height -= y_increment; y_increment++; } } } }
/** * \brief Initializes the movement of the item (if it is falling), * depending on its subtype. */ void Pickable::initialize_movement() { if (is_falling()) { set_movement(new FallingOnFloorMovement(falling_height)); } }