Хотя цикл не работает с операторами 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;
}
Другие вопросы по тегам