/** * @brief Sets the x speed. * @param x_speed the x speed of the object in pixels per second */ void StraightMovement::set_x_speed(double x_speed) { if (std::fabs(x_speed) <= 1E-6) { x_speed = 0; } this->x_speed = x_speed; uint32_t now = System::now(); // compute x_delay, x_move and next_move_date_x if (x_speed == 0) { x_move = 0; } else { if (x_speed > 0) { x_delay = (uint32_t) (1000 / x_speed); x_move = 1; } else { x_delay = (uint32_t) (1000 / (-x_speed)); x_move = -1; } set_next_move_date_x(now + x_delay); } angle = Geometry::get_angle(0, 0, (int) (x_speed * 100), (int) (y_speed * 100)); initial_xy.set_xy(get_xy()); finished = false; notify_movement_changed(); }
/** * @brief Sets the speed to zero. */ void StraightMovement::stop() { double old_angle = this->angle; set_x_speed(0); set_y_speed(0); x_move = 0; y_move = 0; this->angle = old_angle; notify_movement_changed(); }
/** * @brief Changes the direction of the movement vector, keeping the same speed. * * x_speed and y_speed are recomputed so that the total speed is unchanged. * Warning: if x_speed and y_speed are both equal to zero, this function * stops the program on an error message. * * @param angle the new movement direction in radians */ void StraightMovement::set_angle(double angle) { if (!is_stopped()) { double speed = get_speed(); set_x_speed(speed * std::cos(angle)); set_y_speed(-speed * std::sin(angle)); } this->angle = angle; notify_movement_changed(); }
/** * @brief Changes the speed, keeping the same direction of the movement. * * x_speed and y_speed are recomputed so that the movement direction is unchanged. * * @param speed the new speed */ void StraightMovement::set_speed(double speed) { if (x_speed == 0 && y_speed == 0) { x_speed = 1; } // compute the new speed vector double old_angle = this->angle; set_x_speed(speed * std::cos(old_angle)); set_y_speed(-speed * std::sin(old_angle)); this->angle = old_angle; notify_movement_changed(); }
/** * \brief Sets the entity to be controlled by this movement object. * * This entity can be nullptr if your movement applies to something else than a map entity. * However, some subclasses of Movement may require a non nullptr entity because they * implement movements that depend on the map content (e.g. to handle the collisions). * * \param entity The entity to control, or nullptr if the movement should not be * attached to a map entity. */ void Movement::set_entity(Entity* entity) { Debug::check_assertion(drawable == nullptr, "This movement is already assigned to a drawable"); this->entity = entity; if (entity == nullptr) { this->xy = { 0, 0 }; } else { this->xy = entity->get_xy(); notify_movement_changed(); } notify_object_controlled(); }
/** * \brief Sets the drawable to be controlled by this movement object. * * This entity can be nullptr if your movement applies to something else than a drawable. * * \param drawable The drawable to control, or nullptr if the movement should not be * attached to a drawable. */ void Movement::set_drawable(Drawable* drawable) { Debug::check_assertion(entity == nullptr, "This movement is already assigned to an entity"); this->drawable = drawable; if (drawable == nullptr) { this->xy = { 0, 0 }; } else { this->xy = drawable->get_xy(); notify_movement_changed(); } notify_object_controlled(); }
/** * \brief Changes the movement of the entity depending on the direction wanted. * * This function is called when the direction is changed. */ void PlayerMovement::compute_movement() { // compute the speed vector corresponding to the direction wanted by the player if (direction8 == -1) { // no movement stop(); } else { // the directional keys currently pressed define a valid movement set_speed(moving_speed); set_angle(Geometry::degrees_to_radians(direction8 * 45)); } // notify the entity that its movement has just changed: // indeed, the entity may need to update its sprites notify_movement_changed(); }
/** * \brief Chooses a new direction for the movement. */ void RandomMovement::set_next_direction() { double angle; if (get_entity() == NULL || max_radius == 0 // means no limit || bounds.contains(get_x(), get_y())) { // we are inside the bounds (or there is no bound): pick a random direction angle = Geometry::degrees_to_radians(Random::get_number(8) * 45 + 22.5); } else { // we are outside the bounds: get back into the rectangle to avoid going too far angle = Geometry::get_angle(get_x(), get_y(), bounds.get_x() + bounds.get_width() / 2, bounds.get_y() + bounds.get_height() / 2); } set_angle(angle); next_direction_change_date = System::now() + 500 + Random::get_number(1500); // change again in 0.5 to 2 seconds notify_movement_changed(); }