GameEntities.BulletType.GetNeedFireAngleToPosition C# (CSharp) Method

GetNeedFireAngleToPosition() public method

public GetNeedFireAngleToPosition ( float horizontalDistance, float verticalDistance ) : float
horizontalDistance float
verticalDistance float
return float
        public float GetNeedFireAngleToPosition( float horizontalDistance, float verticalDistance )
        {
            float sh = horizontalDistance;
            float sv = verticalDistance;
            float v0 = velocity;

            //!!!!!currently only for big angle fire
            float approximationAngle = MathFunctions.DegToRad( 70 );
            float approximationStep = MathFunctions.DegToRad( 29.9f );

            float nearestsh = 0;

            const int iterationCount = 10;//!!!!!!for howitzers it is more. mb move to method parameter
            for( int iteration = 0; iteration < iterationCount; iteration++ )
            {
                double[] sidesh = new double[ 2 ];

                for( int iterside = 0; iterside < 2; iterside++ )
                {
                    float angle = approximationAngle;
                    if( iterside == 0 )
                        angle += approximationStep;
                    else
                        angle -= approximationStep;

                    if( angle > MathFunctions.PI / 2 )
                        angle = MathFunctions.PI / 2 - .001f;

                    //!!!!!ignore invalid angle (there is a way more correctly)
                    if( angle < MathFunctions.DegToRad( 45 ) )
                    {
                        sidesh[ iterside ] = 100000.0f;
                        continue;
                    }

                    double vh = MathFunctions.Cos16( angle ) * v0;
                    double vv0 = MathFunctions.Sin16( angle ) * v0;

                    double t;
                    {
                        double a = ( -gravity );
                        double b = 2.0 * vv0;
                        double c = -2.0 * sv;

                        double d = b * b - 4.0 * a * c;

                        if( d < 0 )
                            Log.Warning( "BulletType.GetNeedAngleToPosition: d < 0 ({0})", d );

                        double dsqrt = MathFunctions.Sqrt16( (float)d );

                        double x1 = ( -b - dsqrt ) / ( 2.0 * a );
                        double x2 = ( -b + dsqrt ) / ( 2.0 * a );

                        if( x1 < 0 && x2 < 0 )
                            Log.Warning( "BulletType.GetNeedAngleToPosition: x1 < 0 && x2 < 0" );

                        t = Math.Max( x1, x2 );
                    }

                    double calcedsh = vh * t;

                    sidesh[ iterside ] = calcedsh;
                }

                if( Math.Abs( sidesh[ 0 ] - sh ) < Math.Abs( sidesh[ 1 ] - sh ) )
                {
                    approximationAngle += approximationStep;
                    nearestsh = (float)sidesh[ 0 ];
                }
                else
                {
                    approximationAngle -= approximationStep;
                    nearestsh = (float)sidesh[ 1 ];
                }
                approximationStep *= .5f;
            }

            //!!!!admissible error
            if( Math.Abs( horizontalDistance - nearestsh ) > 5 )
                return -1;

            return approximationAngle;
        }