Хотя цикл не работает с операторами bool в C (новичок!)
Я изучаю основы прямо сейчас и делаю простую игру, используя основную графическую библиотеку, предоставленную моим университетом.
- Есть метательный снаряд (путь которого нарисован)
- препятствие (стена) - через которую снаряд не может пройти, поэтому должен пройти
и цель (также должна отображаться сплошной, чтобы линия не прорисовывалась при попадании)
Прямо сейчас мой снаряд брошен прямо через стену
Проблема с циклом while
Любые условия, которые я добавляю (после (y_displacement
(Этот снаряд сам по себе прекращает рисовать, когда y_displacement => FLOOR_HEIGHT (ось Y инвертирована), но любое добавление операторов bool или попытки использовать bool (после #include тоже), чтобы остановить нарисованную линию снаряда, не делают никаких изменения.
ПРОБНАЯ БУЛКА ДЛЯ СТЕНЫ (ничего не меняет):
bool hit_wall = false;
while ((y_displacement < FLOOR_HEIGHT) && (hit_wall == false))
{
time = (x_displacement - X_HAND) / x_velocity; //speed = distance/time
y_displacement = (Y_HAND - y_velocity * time) - (GRAVITY * pow(time, 2)/2);
GFX_DrawLineTo(x_displacement, y_displacement, 3);
x_displacement += 1;
if ((x_displacement == (X_MAX/2.5)) && ((y_displacement > (Y_MAX/2))))
{
hit_wall = true;
}
}
}
Если мне удастся уладить это, я смогу сделать то же самое для моей цели.
Что-то не так с тем, что я делаю?
ФОН:
Полная функция такова:
void throwBall(int(x_position), int(y_position))
{
GFX_SetColour(YELLOW);
int x_mouse;
int y_mouse;
int x_distance;
int y_distance;
double angle;
float initial_velocity;
float x_velocity;
float y_velocity;
float time;
GFX_MoveTo(X_HAND, Y_HAND);
GFX_GetMouseCoordinates(&x_mouse, &y_mouse);
x_distance = x_mouse - X_HAND;
y_distance = y_mouse - Y_HAND;
angle = getAngle(x_distance, y_distance);
initial_velocity = sqrt(pow(x_distance, 2) + pow(y_distance, 2));
//these have been divided by 5 as the magnitude was too large for the window
y_velocity = (initial_velocity * sin (angle) - GRAVITY * time)/(X_MAX/256);
x_velocity = (initial_velocity * cos (angle))/(X_MAX/256);
float y_displacement;
float x_displacement;
x_displacement = X_HAND;
y_displacement = Y_HAND;
bool hit_wall = false;
while ((y_displacement < FLOOR_HEIGHT) && (hit_wall == false))
{
time = (x_displacement - X_HAND) / x_velocity; //speed = distance/time
y_displacement = (Y_HAND - y_velocity * time) - (GRAVITY * pow(time, 2)/2);
GFX_DrawLineTo(x_displacement, y_displacement, 3);
x_displacement += 1;
if ((x_displacement == (X_MAX/2.5)) && ((y_displacement > (Y_MAX/2))))
{
hit_wall = true;
}
}
}
2 ответа
Развивая предыдущие ответы относительно эквивалентности с плавающей точкой и ошибки округления, еще один способ сделать это умножить ваш float
или же double
значение с некоторым коэффициентом 10, чтобы переместить десятичную точку вправо, а затем привести его к int
или же long it
, Затем вы можете сделать логическое сравнение, которое будет на целых числах, которые будут работать надежно. Я упоминаю об этом, потому что иногда может быть проще кодировать, а также читать проще, чем метод epilson (который вы также должны будете использовать для абсолютного значения), описанный в другом ответе.
Главное, что нужно распознать, - это коэффициент 10, на который вы умножаете или устанавливаете epsilon на.
Не сходите с ума и умножайтесь на что-то вроде 1e9 или ставьте epsilon = 1e-9
когда вам не нужно, потому что это может вновь ввести ту же проблему.
Например, если ваши переменные для расстояния указаны в метрах, вам нужно признать, что вам не нужно разрешение больше чем???. Давайте использовать 1/100 миллиметра в качестве примера... насколько вам важно, 1,230012345 мм == 1,230456789 мм. Затем умножьте на 1e5, затем приведите к int или сделайте epsilon=1e-5;
, Тот же принцип применим к единицам дюймов, обычно вам не нужно разрешение больше 0,0001"для всего, что умножается на 1e4 или epsilon = 1e-4.
/* example */
# define D2I 1e2 /* dbl to int factor, 0.01mm resolution */
double x_displacement; /* units of millimeters for this example*/
double y_displacement; /* units of millimeters for this example*/
/* whatever previous calculations result in...
x_displacement having value of 3.00000249687738566
y_displacement having value of 120.00000085639820699
out past 6 or so decimal places a float or double will have arbitrary numbers, so don't multiply by some huge 1e12 number
*/
if ( ( (int)(x_displacement * D2I) == (int)((X_MAX / 2.5) * D2I ) ) &&
( (int)(y_displacement * D2I ) > (int)((Y_MAX / 2 ) * D2I ) )
)
{
hit_wall = true;
}
if ((x_displacement == (X_MAX/2.5)) && ((y_displacement > (Y_MAX/2))))
{
hit_wall = true;
}
вы используете значения flaot, и по некоторым причинам (значения приблизительно) вы почти никогда не получаете в этом, если.
ты должен использовать >
, >=
, <
, <=
poerators, но это также не поможет вам в 100% случаев.
лучший выбор будет использовать epsilon
(Наблюдательная ошибка, Соседство)
лайк
float eps = 0,0000001f;
if ( abs(x_displacement - (X_MAX/2.5) ) < eps
&& y_displacement > ( (Y_MAX/2) - eps ) )
{
hit_wall = true;
}