/** * \brief Updates the position. */ void RelativeMovement::update() { if (entity_followed == nullptr) { finished = true; return; } if (entity_followed->is_being_removed()) { finished = true; entity_followed = nullptr; } else { Point next = entity_followed->get_xy() + entity_offset; Point dnext = next - get_xy(); if (!are_obstacles_ignored()) { if (!finished && (dnext.x != 0 || dnext.y != 0)) { if (!test_collision_with_obstacles(dnext)) { set_xy(next); } else { finished = true; notify_obstacle_reached(); } } } else { set_xy(next); } } }
void StraightMovement::update() { Movement::update(); if(!is_suspended()) { uint32_t now = System::now(); bool current_move_y = move_y != 0 && now >= next_move_date_y; bool current_move_x = move_x != 0 && now >= next_move_date_x; while(current_move_x || current_move_y) { // save current coordinates. Rectangle old_xy(get_x(), get_y()); if(current_move_x) { // time to move in x direction. if(current_move_y) { // time to move in y direction. if(next_move_date_x <= next_move_date_y) { // we first move in x direction. update_x(); if(now >= next_move_date_y) { update_y(); } } else { update_y(); // we first move in y direciton. if(now >= next_move_date_x) { update_x(); } } } else { // we only move in x direction. update_x(); } } else { // we only move in y direction. update_y(); } if(get_entity() != NULL && !finished) { // movement is successful old coordinates have changed. bool success = (get_x() != old_xy.get_x() || get_y() != old_xy.get_y() && (move_x != 0 || move_y != 0)); // no movement notify obstacle. if(!success) { notify_obstacle_reached(); set_finished(); } } // check if we continue wit movement. now = System::now(); current_move_x = move_x != 0 && now >= next_move_date_x; current_move_y = move_y != 0 && now >= next_move_date_y; } } }
/** * @brief Computes the position of the object controlled by this movement. * * This function should be called whenever the angle, the radius or the center changes. */ void CircleMovement::recompute_position() { Rectangle center = this->center_point; if (center_entity != NULL) { center.add_xy(center_entity->get_xy()); } const Rectangle &xy = Geometry::get_xy(center, Geometry::degrees_to_radians(current_angle), current_radius); if (get_entity() == NULL || !test_collision_with_obstacles(xy.get_x() - get_entity()->get_x(), xy.get_y() - get_entity()->get_y())) { set_xy(xy); notify_position_changed(); } else { notify_obstacle_reached(); } }
/** * \brief Computes the position of the object controlled by this movement. * * This function should be called whenever the angle, the radius or the center changes. */ void CircleMovement::recompute_position() { Point center = this->center_point; if (center_entity != nullptr) { center += center_entity->get_xy(); } Point xy = Geometry::get_xy(center, Geometry::degrees_to_radians(current_angle), current_radius); if (get_entity() == nullptr || !test_collision_with_obstacles(xy - get_entity()->get_xy())) { set_xy(xy); notify_position_changed(); } else { notify_obstacle_reached(); } }
/** * \brief Updates the position. */ void FollowMovement::update() { if (entity_followed == NULL) { finished = true; return; } if (entity_followed->is_being_removed()) { finished = true; RefCountable::unref(entity_followed); entity_followed = NULL; } else { int next_x = entity_followed->get_x() + x; int next_y = entity_followed->get_y() + y; int dx = next_x - get_x(); int dy = next_y - get_y(); if (!are_obstacles_ignored()) { if (!finished && (dx != 0 || dy != 0)) { if (!test_collision_with_obstacles(dx, dy)) { set_x(next_x); set_y(next_y); } else { finished = true; notify_obstacle_reached(); } } } else { set_x(next_x); set_y(next_y); } } }
/** * @brief Updates the position of the object controlled by this movement. * * This function is called repeatedly. */ void StraightMovement::update() { if (!is_suspended()) { uint32_t now = System::now(); bool x_move_now = x_move != 0 && now >= next_move_date_x; bool y_move_now = y_move != 0 && now >= next_move_date_y; while (x_move_now || y_move_now) { // while it's time to move // save the current coordinates Rectangle old_xy(get_x(), get_y()); if (x_move_now) { // it's time to make an x move if (y_move_now) { // but it's also time to make a y move if (next_move_date_x <= next_move_date_y) { // x move first update_x(); if (now >= next_move_date_y) { update_y(); } } else { // y move first update_y(); if (now >= next_move_date_x) { update_x(); } } } else { update_x(); } } else { update_y(); } if (!is_suspended() && get_entity() != NULL && !finished) { // the movement was successful if the entity's coordinates have changed // and the movement was not stopped bool success = (get_x() != old_xy.get_x() || get_y() != old_xy.get_y()) && (x_move != 0 || y_move != 0); if (!success) { notify_obstacle_reached(); } } now = System::now(); if (!finished && max_distance != 0 && Geometry::get_distance(initial_xy.get_x(), initial_xy.get_y(), get_x(), get_y()) >= max_distance) { set_finished(); } else { x_move_now = x_move != 0 && now >= next_move_date_x; y_move_now = y_move != 0 && now >= next_move_date_y; } } } // Do this at last so that Movement::update() knows whether we are finished. Movement::update(); }