2009-03-17 9 views
1

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

- (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)); 
    } 

} 

ответ

2

Если uBalloon массив ваша итерация должна находиться в диапазоне от 0 (п-1).

E.g.

for (CurBalloon=0; CurBalloon < NumBalloons; ++CurBalloon) 
{ 
    uBalloon[curBalloon] // blah 
} 
+0

Вы должны исправить это для CurBalloon schnaader

+0

другой, спасибо. –

2
[...] 
if ((deltaX*deltaX + deltaY*deltaY) == -1) { 
    return sqrtf(-.99); 
} else { 
[...] 

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

+1

Кроме того, сумма двух квадратов никогда не может быть отрицательной. Не то чтобы вы могли надежно проверять равенство, используя ==, в любом случае. – aib

+0

ОК, так что это не нужно, но не проблема. – schnaader

+0

Я думал, что это может никогда не пойти отрицательно ... удалив эту часть. Спасибо. –

1

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

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

+0

Спасибо, я долго не работал с объективным C. Я изменил его на atan2f. Кроме того, спасибо за указание повторных вызовов. –