C ++ gamedev: усечение float для int - PullRequest
14 голосов
/ 31 октября 2011

Я делаю игру на C ++, где есть танк, который может двигаться на сцене. У танка есть угол (плавать в градусах, и я предполагаю, что танк находится в 0º, когда его пушка указывает вправо), скорость (плавание), и есть постоянная времени, называемая «deltaT» (плавание).

Когда игрок двигает танк вперед, я использую тригонометрию и физическое уравнение положения в зависимости от времени (я имею в виду X (t), я не знаю, как это говорит по-английски), чтобы вычислить новый танк координаты на сцене.

Это моя проблема: из-за перехода от типа float к int значения, близкие к нулю, не учитываются. Таким образом, под определенными углами танк выглядит повернутым, но движется в другом направлении.

Вот что делает мой код:

1 - сначала я разделяю скорость на составляющие X и Y, используя угол, в котором движется танк:

    float speedX = this->speed * cos(this->angle);
    float speedY = this->speed * sin(this->angle);

2 - затем используйте уравнение, которое я упомянул выше, чтобы получить новые координаты:

    this->x = (int) ceil(this->x + (speedX * deltaT));
    this->y = (int) ceil(this->y - (speedY * deltaT));

Проблема начинается с первого шага: под определенными углами значение cos или sin очень близко к нулю. Итак, когда я умножил его на скорость, чтобы получить, скажем, speedX, я все равно получил очень низкое число, а затем, когда я умножил его на deltaT, оно все еще слишком мало, и, наконец, когда применил ceil, эта сумма полностью потерялась.

Например, при 94º, с deltaT = 1,5 и скоростью = 2, и предполагая, что начальное значение X равно 400, мы имеем:

speedX = -0.1395...
this->x = 400 //it must be 399.86..., but stays in 400 due to the ceiling

Итак, в моей игре танк вращается, но движется прямо вперед. Кроме того, иногда он движется хорошо назад, но не вперед, и наоборот.

¿Как мне сделать направление танка более точным? Увеличить скорость или значение deltaT нельзя, поскольку речь идет о танке, а не о формуле 1: P

Ответы [ 3 ]

9 голосов
/ 31 октября 2011

Как мне сделать направление танка более точным? Увеличить скорость или значение deltaT нельзя, поскольку речь идет о танке, а не о формуле 1: P

Вы должны хранить значения позиций как float с, даже если они в конечном итоге используются как int с для позиционирования на экране. Таким образом, вы не потеряете нецелую часть своей позиции. Просто наберите int в самом конце, когда будете рисовать.

5 голосов
/ 31 октября 2011

Сохраняйте местоположение танка в float с все время. В качестве альтернативы, позвольте резервуару вращаться с шагом 45 градусов. Решите, будет ли ваша игра использовать приблизительные позиции и заголовки или точные, и придерживайтесь этого решения на всем протяжении.

0 голосов
/ 05 апреля 2018

Ваша проблема не в точности! Математика с плавающей точкой имеет 24-битную точность, это плюс / минус 1/16 777 216. Там нет проблем.

Это ваш режим округления . ceil округляет вверх.

Попробуйте:

int x = this->x + (speedX * deltaT) +.5f;

ceil создает ошибку округления (E) 0

Кроме того, избегайте использования двойной математики. ceil - это двойная версия, вы имеете в виду ceilf. Технически, ваш код использует float-> double-> int. Вы ничего не получите от этого, но на это нужно время.

И наконец ... Реальная проблема:

Ваша проблема точности на самом деле в том, что вы ее накапливаете! Итак, 0 при 60 Гц => 0 Если X / Y - это пиксельные координаты, это целый экран! Не удивительно, что вы боретесь.

Независимо от того, как вы округлились, это всегда будет проблемой. Вместо этого вы должны сохранить результат с плавающей запятой перед округлением. Таким образом, абсолютная ошибка всегда равна 0

this->XPos += speedX * deltaT;
this->YPos += speedY * deltaT;
this->x = static_cast<int>(this->XPos+.5f);
this->y = static_cast<int>(this->YPos+.5f);

Теперь вы должны плавно двигаться.

PS: слово на английском языке "параметрическое", https://en.wikipedia.org/wiki/Parametric_equation

...