Example #1
0
    //определение, может ли самолет повернуть в указанную точку без дополнительных виражей
    private bool CanBeReached(Vector3 position, ref float speed)
    {
        Vector3 toPosition      = position - Position;
        Vector3 toPositionLocal = transform.InverseTransformDirection(toPosition);

        //если точка находится почти на прямой перед нами - можно смело лететь
        if (toPositionLocal.z >= 0 && Mathf.Abs(toPositionLocal.x) < 0.0001f)
        {
            speed = CorrectSpeed(speed, _maxSpeed);
            return(true);
        }

        //определение по относительному положению точки угловой скорости со знаком, чтобы довернуть до нее
        float angSpeed = _angularSpeed;

        if (toPositionLocal.x < 0)
        {
            angSpeed = -_angularSpeed;
        }

        float maneurRadius;
        //определяем центр радиуса виража, и сам радиус при минимальной скорости
        Vector3 maneurCenter = AngularMath.CircleCenter(
            Position, Direction * _minSpeed, angSpeed, out maneurRadius
            );

        if (_debug)
        {
            Debug.DrawRay(maneurCenter, (Position - maneurCenter).normalized * maneurRadius, Color.cyan);
        }

        float fromCenterToPosition = Vector3.Distance(position, maneurCenter);

        //если расстояние от центра виража до самолема меньше радиуса,
        //то точка находится внутри виража, и достичь ее не можем
        if (fromCenterToPosition < maneurRadius)
        {
            speed = CorrectSpeed(speed, _minSpeed);
            return(false);
        }

        //точка находится где-то за пределами виража,
        //нужно расчитать скорость, на которой самолет сможет в нее попасть
        float radiusRate     = fromCenterToPosition / maneurRadius;
        float moneurMaxSpeed = radiusRate * _minSpeed;

        speed = CorrectSpeed(speed, moneurMaxSpeed);
        return(true);
    }
Example #2
0
    //находит точку захода посадку
    //чем более "правильное" положение занимает самолет относительно корабля, тем точка ближе к месту посадки,
    //"доводя" таким образом самолет до нужного направления захода на палубу
    private Vector3 GetStartLandingPoint()
    {
        CarrierDispatch carrier = flight.carrier;

        //сначала рассчитываем время прогноза позиции корабля
        float toCarrierDistance       = Vector3.Distance(Position, carrier.Position);
        float toCarrierTime           = toCarrierDistance / _minSpeed;
        float toCarrierDirectionAngle = Vector3.Angle(carrier.Direction, Direction);
        float toCarrierDirectionTime  = toCarrierDirectionAngle / _angularSpeed;
        float forecastTime            = toCarrierTime + toCarrierDirectionTime;
        //на основе времени прогноза расчитываем направление и позуцию корабля
        Quaternion forecastRotation;
        Vector3    forecastCarrierPosition = AngularMath.Forecast(
            carrier.Position,
            carrier.Direction * -Mathf.Abs(carrier.LinearSpeed),
            carrier.AngularSpeed,
            forecastTime,
            out forecastRotation
            );

        //расчитываем величину доворота курса до прогнозируемой позиции корабля до прогнозируемого направления корабля,
        Vector3 forecastCarrierDirection  = forecastRotation * carrier.Direction;
        Vector3 toForecastCarrierPosition = forecastCarrierPosition - Position;
        //это даст понимание расположения самолета относительно корабля в его прогнозируемой позиции
        Vector3 fromToCarrierToForecastDirectionEuler =
            Quaternion.FromToRotation(toForecastCarrierPosition, forecastCarrierDirection).eulerAngles -
            new Vector3(0, 180, 0);

        //на основе предыдущего расчета, определяем, в какую сторону должен будет поворачивать самолет
        float signedAngSpeed = _angularSpeed;

        if (fromToCarrierToForecastDirectionEuler.y > 0)
        {
            signedAngSpeed = -signedAngSpeed;
        }
        //коррекция угловой скорости самолета на угловую скорость корабля
        if (carrier.LinearSpeed > 0)
        {
            signedAngSpeed += Mathf.Max(carrier.AngularSpeed, 0);
        }
        else if (carrier.LinearSpeed < 0)
        {
            signedAngSpeed -= Mathf.Min(carrier.AngularSpeed, 0);
        }

        float maneurRadius;
        //расчет центра маневра от прогнозирумых позиции и нарпавления корабля
        Vector3 maneurCenter = AngularMath.CircleCenter(
            forecastCarrierPosition,
            forecastCarrierDirection * LinearSpeed,
            signedAngSpeed,
            out maneurRadius
            );

        if (_debug)
        {
            Vector3    radius = Vector3.forward * maneurRadius;
            Quaternion oneGeg = Quaternion.AngleAxis(1, Vector3.up);
            for (int i = 0; i < 360; i++)
            {
                Vector3 debugPoint = maneurCenter + radius;
                Debug.DrawRay(debugPoint, Vector3.up, Color.white);
                radius = oneGeg * radius;
            }
        }

        //строим гопотенузу прямого треугольника для расчета касательной
        Vector3 toManeurCenter = maneurCenter - Position;
        //расчет длины касатльной от позиции самолета к траектории виража на посадку
        float distanceToTangentPoint = Mathf.Pow(toManeurCenter.magnitude, 2) - Mathf.Pow(maneurRadius, 2);

        //если длина касательной не положительна, то мы находимся внутри траектории виража,
        //надо отлетать от корабля, но можно поропбовать зайти на посадку
        if (distanceToTangentPoint <= 0)
        {
            return(carrier.Position);
        }
        distanceToTangentPoint = Mathf.Pow(distanceToTangentPoint, 0.5f);

        //строим основу для касательной от гипотенузы (центр виража - позиция самолета)
        Vector3 toManeurTangent = toManeurCenter.normalized * distanceToTangentPoint;
        //определяем угол между гипотенузой и касательной
        float toManeurTangentRotateSin   = maneurRadius / toManeurCenter.magnitude;
        float toManeurTangetnRotateAngle = Mathf.Asin(toManeurTangentRotateSin) * 180 / Mathf.PI;

        if (signedAngSpeed > 0)
        {
            toManeurTangetnRotateAngle = -toManeurTangetnRotateAngle;
        }
        //для поворота заготовки касательной
        Quaternion rotateToManeurTangent = Quaternion.AngleAxis(toManeurTangetnRotateAngle, Vector3.up);

        //построение касательной от позиции самолета к траектории входа на посадку
        toManeurTangent = rotateToManeurTangent * toManeurTangent;
        //определние точки входа в траекторию посадки
        return(Position + toManeurTangent);
    }