/** * \brief Notifies this movement that the object it controls has changed. */ void TargetMovement::notify_object_controlled() { StraightMovement::notify_object_controlled(); // Coordinates have changed: compute a new trajectory. recompute_movement(); }
/** * \brief Updates the position. */ void PathFindingMovement::update() { PathMovement::update(); if (target != nullptr && target->is_being_removed()) { target = nullptr; } if (is_suspended()) { return; } if (PathMovement::is_finished()) { // there was a collision or the path was made if (target != nullptr && System::now() >= next_recomputation_date && get_entity()->is_aligned_to_grid()) { recompute_movement(); } else { set_path(create_random_path()); } } }
/** * @brief Changes the target of this movement. * @param target_x x coordinate of the target point * @param target_y y coordinate of the target point */ void TargetMovement::set_target(int target_x, int target_y) { this->target_x = target_x; this->target_y = target_y; recompute_movement(); next_recomputation_date = System::now() + recomputation_delay; }
/** * @brief Changes the target of this movement. * @param target_entity the target entity */ void TargetMovement::set_target(MapEntity* target_entity) { this->target_entity = target_entity; this->target_x = target_x; this->target_y = target_y; recompute_movement(); next_recomputation_date = System::now() + recomputation_delay; }
/** * \brief Creates a stream action. * \param stream The stream applied. * \param entity_moved Entity the stream is applied to. */ StreamAction::StreamAction(Stream& stream, Entity& entity_moved): stream(std::static_pointer_cast<Stream>(stream.shared_from_this())), entity_moved(std::static_pointer_cast<Entity>(entity_moved.shared_from_this())), active(true), suspended(false), when_suspended(0), target(0, 0), next_move_date(0), delay(0) { recompute_movement(); next_move_date = System::now() + delay; }
/** * @brief Updates the movement. */ void TargetMovement::update() { if (System::now() >= next_recomputation_date) { recompute_movement(); next_recomputation_date += recomputation_delay; } // see if the target is reached int dx = target_x - get_x(); int dy = target_y - get_y(); if (dx * sign_x <= 0 && dy * sign_y <= 0) { if (!test_collision_with_obstacles(dx, dy)) { set_xy(target_x, target_y); // because the target movement may have not been very precise stop(); finished = true; } } StraightMovement::update(); }
/** * \brief Changes the target of this movement. * \param target_entity The entity to target or NULL. * \param x X of the target point, or X offset in the case of an entity. * \param y Y of the target point, or Y offset in the case of an entity. */ void TargetMovement::set_target(MapEntity* target_entity, int x, int y) { if (this->target_entity != NULL) { this->target_entity->decrement_refcount(); if (this->target_entity->get_refcount() == 0) { delete this->target_entity; } } this->target_entity = target_entity; if (this->target_entity != NULL) { this->target_entity->increment_refcount(); this->entity_offset_x = x; this->entity_offset_y = y; } else { this->target_x = x; this->target_y = y; } recompute_movement(); next_recomputation_date = System::now() + recomputation_delay; }
/** * \brief Called repeatedly by the main loop. * Updates the effect of the stream on the entity. */ void StreamAction::update() { // If the action is already disabled, do nothing. if (!is_active()) { return; } // First check that the stream and the entity still exist // and are enabled. if (stream->is_being_removed()) { stream = nullptr; active = false; return; } if (!stream->is_enabled()) { active = false; return; } if (entity_moved->is_being_removed()) { entity_moved = nullptr; active = false; return; } if (!entity_moved->is_enabled()) { active = false; return; } // Stop the stream action if the hero escapes a non-blocking stream. const Point& ground_point = entity_moved->get_ground_point(); if ( stream->get_allow_movement() && !stream->overlaps(ground_point) // We are no longer on the stream. ) { // Blocking streams are more special. // The hero cannot escape them so we don't need this. // Also, diagonal blocking streams continue // to move the entity even when it does not overlap anymore. // This is needed to have precise // exact diagonal movements of 16 pixels in stream mazes. if (entity_moved->get_distance(target) > 8) { // This last test is to avoid stopping a stream when being close to the target. // Indeed, in the last pixels before the target, the entity's ground // point is no longer on the stream. We continue anyway until the target. active = false; return; } } if (is_suspended()) { return; } // Update the position. recompute_movement(); while ( System::now() >= next_move_date && is_active() ) { next_move_date += delay; int dx = 0; int dy = 0; if (target.x > entity_moved->get_x()) { dx = 1; } else if (target.x < entity_moved->get_x()) { dx = -1; } if (target.y > entity_moved->get_y()) { dy = 1; } else if (target.y < entity_moved->get_y()) { dy = -1; } if (test_obstacles(dx, dy)) { bool collision = true; // Collision with an obstacle: try only X or only Y. if (dx != 0 && dy != 0) { if (!test_obstacles(dx, 0)) { dy = 0; collision = false; } else if (!test_obstacles(0, dy)) { dx = 0; collision = false; } } if (collision) { if (!stream->get_allow_movement()) { // Stop the stream if it was a blocking one. active = false; } break; } } entity_moved->set_xy(entity_moved->get_x() + dx, entity_moved->get_y() + dy); entity_moved->notify_position_changed(); // See if the entity has come outside the stream, // in other words, if the movement is finished. if (has_reached_target()) { // The target point is reached: stop the stream. active = false; } recompute_movement(); } }
/** * \brief Sets the speed of this movement when it is not stopped. * \param moving_speed the speed when moving, in pixels per second */ void TargetMovement::set_moving_speed(int moving_speed) { this->moving_speed = moving_speed; recompute_movement(); }