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;
}