Не ошибка числа (NAN), делающая обнаружение столкновения в приложении iphone - PullRequest
1 голос
/ 18 марта 2009

У меня есть набор воздушных шаров, которые я пытаюсь заставить отскакивать друг от друга, как шары. Когда я начинаю их перемещать и затем обнаруживаю столкновение, процедура столкновений в конечном итоге возвращает NAN для скорости воздушных шаров. Я в конечном итоге с позицией что-то вроде х = 270, у = -nan (0x400000). Я искал код весь день и до сих пор не могу найти ошибку, любая помощь будет признательна. Вот код:

 - (void)MoveBalloons {

    for (CurBalloon=1; CurBalloon <= NumBalloons; ++CurBalloon) {

    //check for edge hCurBalloont
    if (uBalloon[CurBalloon].pos.y > 456) {
        uBalloon[CurBalloon].pos.y = 456;
        uBalloon[CurBalloon].Vel_y = -uBalloon[CurBalloon].Vel_y;
    }
    if (uBalloon[CurBalloon].pos.y < 24) {
        uBalloon[CurBalloon].pos.y = 24;
        uBalloon[CurBalloon].Vel_y = -uBalloon[CurBalloon].Vel_y;
    }
    if (uBalloon[CurBalloon].pos.x > 289) {
        uBalloon[CurBalloon].pos.x = 289;
        uBalloon[CurBalloon].Vel_x = -uBalloon[CurBalloon].Vel_x;
    }
    if (uBalloon[CurBalloon].pos.x < 31) {
        uBalloon[CurBalloon].pos.x = 31;
        uBalloon[CurBalloon].Vel_x = -uBalloon[CurBalloon].Vel_x;
    }

    //call loop to go through the balloons for each touch.
    //[self CollisionCheck];

        NSUInteger h;
        float dist, tempvelx, tempvely, temp2velx, temp2vely;;

        for (h=1; h <= NumBalloons; ++h) {
            //check if balloon is too close
            if (CurBalloon == h) { //skip the check ifit's the same balloon
            } else {
                dist = distanceBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos);
                if (dist <= (kBalloonNear)) { //balloon's touching

                    tempvelx = uBalloon[CurBalloon].Vel_x;
                    tempvely = uBalloon[CurBalloon].Vel_y;
                    temp2velx = uBalloon[h].Vel_x;
                    temp2vely = uBalloon[h].Vel_y;

                    tempvelx = (uBalloon[CurBalloon].Vel_x - uBalloon[h].Vel_x) * (sinf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos)))*(uBalloon[CurBalloon].Vel_x - uBalloon[h].Vel_x) * (sinf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos))) - (uBalloon[CurBalloon].Vel_y - uBalloon[h].Vel_y) * sinf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) * cosf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) + uBalloon[h].Vel_x;

                    tempvely = (uBalloon[CurBalloon].Vel_y - uBalloon[h].Vel_y) * (cosf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos))) * (uBalloon[CurBalloon].Vel_y - uBalloon[h].Vel_y) * (cosf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos))) - (uBalloon[CurBalloon].Vel_x - uBalloon[h].Vel_x) * sinf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) * cosf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) + uBalloon[h].Vel_y;

                    temp2velx = (uBalloon[CurBalloon].Vel_x - uBalloon[h].Vel_x) * (cosf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos))) * (uBalloon[CurBalloon].Vel_x - uBalloon[h].Vel_x) * (cosf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos))) + (uBalloon[CurBalloon].Vel_y - uBalloon[h].Vel_y) * sinf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) * cosf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) + uBalloon[h].Vel_x;

                    temp2vely = (uBalloon[CurBalloon].Vel_y - uBalloon[h].Vel_y) * (sinf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos)))*(uBalloon[CurBalloon].Vel_y - uBalloon[h].Vel_y) * (sinf(angleBetweenPoints(uBalloon[CurBalloon].pos,uBalloon[h].pos))) - (uBalloon[CurBalloon].Vel_x - uBalloon[h].Vel_x) * sinf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) * cosf(angleBetweenPoints(uBalloon[CurBalloon].pos, uBalloon[h].pos)) + uBalloon[h].Vel_y;

                    uBalloon[CurBalloon].Vel_x = tempvelx;  
                    uBalloon[CurBalloon].Vel_y = tempvely;
                    uBalloon[h].Vel_x = temp2velx;  //set to old value of CurBalloon balloon.
                    uBalloon[h].Vel_y = temp2vely;

                }
            }
        }


    if (fabsf(uBalloon[CurBalloon].Vel_x) >= kBalloonMaxSpeed) uBalloon[CurBalloon].Vel_x = kBalloonMaxSpeed;
    if (fabsf(uBalloon[CurBalloon].Vel_y) >= kBalloonMaxSpeed) uBalloon[CurBalloon].Vel_y = kBalloonMaxSpeed;
    if (fabsf(uBalloon[CurBalloon].Vel_x) <= -kBalloonMaxSpeed) uBalloon[CurBalloon].Vel_x = -kBalloonMaxSpeed;
    if (fabsf(uBalloon[CurBalloon].Vel_y) <= -kBalloonMaxSpeed) uBalloon[CurBalloon].Vel_y = -kBalloonMaxSpeed;



    if (uBalloon[CurBalloon].Vel_y > KBalloonSpeed) { //if travellCurBalloonng fast, slow CurBalloont up fast to normal speed
        uBalloon[CurBalloon].Vel_y = uBalloon[CurBalloon].Vel_y - kBalloonSlowRate;
    }
    if (uBalloon[CurBalloon].Vel_x > KBalloonSpeed) { //if travellCurBalloonng fast, slow CurBalloont up fast to normal speed
        uBalloon[CurBalloon].Vel_x = uBalloon[CurBalloon].Vel_x - kBalloonSlowRate;
    }
    if (uBalloon[CurBalloon].Vel_y < KBalloonSpeed) { //if travellCurBalloonng fast, slow CurBalloont up fast to normal speed
        uBalloon[CurBalloon].Vel_y = uBalloon[CurBalloon].Vel_y + kBalloonSlowRate;
    }
    if (uBalloon[CurBalloon].Vel_x < KBalloonSpeed) { //if travellCurBalloonng fast, slow CurBalloont up fast to normal speed
        uBalloon[CurBalloon].Vel_x = uBalloon[CurBalloon].Vel_x + kBalloonSlowRate;
    }


    //slow to 0 if velocCurBalloonty CurBalloons CurBalloonnsCurBalloonde the slow rate
    if (fabsf(uBalloon[CurBalloon].Vel_x) <= kBalloonSlowRate) uBalloon[CurBalloon].Vel_x = 0;
    if (fabsf(uBalloon[CurBalloon].Vel_y) <= kBalloonSlowRate) uBalloon[CurBalloon].Vel_y = 0;

    uBalloon[CurBalloon].Vel_x = uBalloon[CurBalloon].Vel_x - kBalloonFallRate; //keep movCurBalloonng down     

    //add velocCurBalloonty to poCurBalloonnts
    uBalloon[CurBalloon].pos.y= uBalloon[CurBalloon].pos.y + uBalloon[CurBalloon].Vel_y;    
    uBalloon[CurBalloon].pos.x = uBalloon[CurBalloon].pos.x + uBalloon[CurBalloon].Vel_x;

    }
}

Вот функции, написанные на c, которые используются для расстояния и угла. Я даже проверяю, чтобы никогда не было sqrt (-1) и деление на 0:

 CGFloat distanceBetweenPoints (CGPoint first, CGPoint second) {
    CGFloat deltaX = second.x - first.x;
    CGFloat deltaY = second.y - first.y;
    if ((deltaX*deltaX + deltaY*deltaY ) == -1) {
        return sqrtf(-.99);
    } else {
    return sqrtf(deltaX*deltaX + deltaY*deltaY );
    }
}

    CGFloat angleBetweenPoints(CGPoint first, CGPoint second) {

    if (first.x - second.x == 0)  {
        return (pi / 2);
    } else {
        return atanf((first.y-second.y) / (first.x - second.x));
    }

}

Ответы [ 3 ]

2 голосов
/ 18 марта 2009
[...]
if ((deltaX*deltaX + deltaY*deltaY ) == -1) {
    return sqrtf(-.99);
} else {
[...]

Я думаю, что это ваша проблема (или одна из них). Вы не можете получить квадратный корень из отрицательного числа (и не имеет значения, -1 или -.99).

2 голосов
/ 18 марта 2009

Если uBalloon является массивом, ваша итерация должна быть между 0: (n-1).

* 1003 Е.Г. *

for (CurBalloon=0; CurBalloon < NumBalloons; ++CurBalloon)
{
  uBalloon[curBalloon] // blah
}
1 голос
/ 18 марта 2009

Возможно, это не источник вашей ошибки, но эта функция не совсем верна:

CGFloat angleBetweenPoints(CGPoint first, CGPoint second) {

if (first.x - second.x == 0)  {
        return (pi / 2);
} else {
        return atanf((first.y-second.y) / (first.x - second.x));
}

Это всегда будет возвращать угол между -pi / 2 и + pi / 2, и это может вернуть неверный результат, если first.x - second.x очень мало и близко к 0, но не точно 0. Вместо этого просто используйте atan2

CGFloat angleBetweenPoints(CGPoint first, CGPoint second) {
    return atan2f(first.y - second.y, first.x - second.x);
}

atan2() возвращает полный диапазон углов от -pi до + pi и соответствующим образом обрабатывает края. Это, вероятно, не повлияет на вас, так как вы просто берете sin / cos полученного угла. Однако вы делаете это очень неэффективно - вы звоните angleBetweenPoints() 8 (!) Раз, когда результат одинаков, и занимает 4 sin() с и 4 cos() с. Вы можете пропустить всю тригонометрию и просто использовать геометрию похожих треугольников, чтобы получить одинаковые результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...