Vector2.Normalize (EndPosition - StartPosition) равен NaN Что я могу сделать? - PullRequest
0 голосов
/ 30 марта 2020

Иногда два вектора EndPosition и StartPosition имеют абсолютно одинаковые значения в моем приложении. В этом случае Vector2.Normalize (EndPosition - StartPosition) имеет значение NaN, и мое приложение впоследствии останавливается, потому что позже в моем коде используется переменное направление.

Что я могу сделать, если два вектора EndPosition и StartPosition имеют точно одинаковые значения? Как я могу проверить, является ли направление NaN? Я просто хочу выполнить следующий блок кода (после direction = Vector2.Normalize (EndPosition - StartPosition);), если переменная direction не NaN.

Например:

  float distance;
  Vector2 direction;
  Vector2 StartPosition = new Vector2(400, 250);
  Vector2 EndPosition = new Vector2(400, 250);

  distance = Vector2.Distance(StartPosition, EndPosition);
  direction = Vector2.Normalize(EndPosition - StartPosition);
  // code where I use direction to calculate

1 Ответ

0 голосов
/ 07 апреля 2020

Просто чтобы дать ответ на этот вопрос (кредит InBetween и Toby60) и предложить несколько советов:

Любая операция, включающая NaN значения, возвращает NaN. Когда Vector2 передается spriteBatch.Draw, содержащему NaN, вызов ничего не рисует на экране, более конкретно, он рисуется в месте Int32.MinValue, см. в этой статье для получения дополнительной информации. .

Используйте квадрат расстояния или расстояние Манхэттена, когда это возможно. Квадратная root функция (вызывается в Vector2.Distance() или Vector2 .Length()) на порядок медленнее, чем умножение другой стороны на себя и проверка на это значение.

Удаление квадрата root невозможно при нормализации Vector2, но вы можете сначала вычислить длину вектора и использовать это значение для исключения вызова второго квадрата root, а также два вызова функций.

Сначала вычтите два Vector и сохраните это значение. Этот метод устраняет необходимость отдельного вычитания тех же значений позже и предоставляет способ реализации логарифмического c (запускается быстро и замедляется по мере приближения) паттерн движения:

velocity = direction * .25f; // each Update it moves a quarter of the 
//distance to the target `EndPosition` 

Вот код, указанный в приведенных выше модификациях.

float distance;
Vector2 direction;
Vector2 StartPosition = new Vector2(400, 250);
Vector2 EndPosition = new Vector2(400, 250);

direction = EndPosition - StartPosition;  // subtract first 
distance = direction.Length();

if(distance > 0.000001f) // compare to small non-zero value
   direction /= distance; // by definition of Normalize(), eliminates the second square root
else
   direction = Vector2.Zero;

// code where I use direction to calculate

Следующий код добавляет скорость и переименовывает StartPosition в Position, добавляет Velocity и устраняет «встряску» после ее прибытия .

// class level variables
float distance;
float speed = 4;
Vector2 direction;
Vector2 Velocity;
Vector2 Position;
Vector2 EndPosition = new Vector2(400, 250);

// inside of the Update method

direction = EndPosition - Position;  // subtract first 
if (direction.LengthSquared > .00001f) //eliminates the rest of the code if this quick check fails 
{
   distance = direction.Length();

   if(distance > 0.000001f) // compare to small non-zero value
      direction /= distance; // by definition of Normalize(), eliminates the second square root
   else
      direction = Vector2.Zero;
   Velocity = direction;
   if (distance > speed)
      Position += Velocity * speed;
   else
      Position += direction * .5f; // we do not want position flip-flopping around EndPosition, so move speed /2 and then speed /4 ...
}
else
{
   direction = Vector2.Zero; 
   Velocity =  Vector2.Zero;
}// just in case direction or Velocity is needed later, otherwise remove the else up to this line
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...