Пример #1
0
/**
 * \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);
    }
  }
}
Пример #2
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;
}
Пример #3
0
/**
 * @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;
}
Пример #4
0
/**
 * \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;
}
Пример #5
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;
}
Пример #6
0
/**
 * \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;
}
Пример #7
0
/**
 * \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);
        }
    }
}
Пример #8
0
/**
 * @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();
    }
  }
}
Пример #9
0
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);
}
Пример #10
0
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);
}
Пример #11
0
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);
    }
  }
}
Пример #12
0
/**
 * \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();
}
Пример #13
0
/**
 * \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();
}
Пример #14
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");
}
Пример #15
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, 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);
		}
	
}
Пример #17
0
/**
 * \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));
    }
  }
}
Пример #18
0
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;
        }
    }
}
Пример #19
0
/**
 * \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;
}
Пример #20
0
/**
 * \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
      ));
    }
  }
}
Пример #21
0
/**
 * \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
  }
}
Пример #22
0
/**
 * \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]);
}
Пример #24
0
/**
 * @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);
}
Пример #25
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));
}
Пример #26
0
/**
 * \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));
  }
}
Пример #27
0
/**
 * \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++;
      }
    }
  }
}
Пример #28
0
/**
 * \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();
  }
}
Пример #29
0
/**
 * @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++;
      }
    }
  }
}
Пример #30
0
/**
 * \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));
    }
}