/// <summary> /// Расчитать начальную скорость, чтобы переместить обьект с начала движения до самого конца. /// Перемещение будет расчитано с учетом горизонтального и вертикального движения. (как если кинуть камень или запустить стрелу) /// </summary> /// <param name="pos"></param> /// <param name="targetPos"></param> /// <returns></returns> public static float2 GetVelocity(float3 pos, float2 targetPos, float absoluteVelocity, float2 acceleration) { //изначально имеем систему: // | delta.x = VxT + AxT^2/2 (1) // < delta.y = VyT + AyT^2/2 (2) // | V = Sqrt(Vx^2 + Vy^2) (3) //сначала подсчитаем перемещение var delta = pos.GetDirectionTo(targetPos);//иииизи //подсчитаем время, для выполнения перемещения... //из (2) получаем Vy и подставляем в (3) //получаем: |Vy| = Sqrt(V^2 - (delta.x/T - AxT/2)^2) //раскрывая модуль, отбросим отрицательное значение. т.к. нам надо положительное значение скорости Vy //подставляем Vy в (2) уравнение и получем уравнение с T^4... //считая что T^2 = N, находим N из квадратного уравнения: var a = -acceleration.x * acceleration.x - acceleration.y * acceleration.y; var b = 4 * (absoluteVelocity * absoluteVelocity + delta.x * acceleration.x + delta.y * acceleration.y); var c = 4 * (-delta.x * delta.x - delta.y * delta.y); float2 n2; var hasResult = ANU.Utils.Math.SolveQuadraticEquation(new Math.QuadraticEquation(a, b, c), out n2); //так как n - это T^2, то n > 0. Более того, нас интересует минимильное вермя. if (!hasResult || (n2.x <= 0 && n2.y <= 0)) { //хз что делать... пускай под 45 грудусов будет... return(new float2(absoluteVelocity * math.sign(delta.x), absoluteVelocity) / math.SQRT2); } var n = math.min(n2.x, n2.y); if (n <= 0) { n = math.max(n2.x, n2.y); } //|T| = Sqrt(n). Отрицательное значение отбрасываем. Т.к. нам надо положительное время... var time = math.sqrt(n); //ну и подставляем найденное Т в формулы (1) и (2) float2 velocity = float2.zero; velocity.x = delta.x / time - acceleration.x * time / 2; velocity.y = delta.y / time - acceleration.y * time / 2; return(velocity); }