2009-03-17 7 views
1

J'ai un ensemble de ballons que j'essaie de faire rebondir les uns sur les autres comme des balles. Quand je commence à les déplacer et ensuite détecter une collision, la routine pour les collisions retourne finalement un NAN pour la vélocité des ballons. Je me retrouve avec une position de quelque chose comme x = 270, y = -nan (0x400000). J'ai regardé le code toute la journée et je n'arrive toujours pas à trouver l'erreur, toute aide serait appréciée. Voici le code:Pas une erreur de numéro (NAN) faisant la détection de collision dans une application 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; 

    } 
} 

Voici les fonctions écrites en c qui sont utilisées pour la distance et l'angle. Je suis même en vous assurant de ne jamais avoir un sqrt (-1) et division par 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)); 
    } 

} 

Répondre

2

Si uBalloon est un tableau de votre itération doit être comprise entre 0: (n-1).

E.g.

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

Vous devriez corriger ceci à CurBalloon schnaader

+0

un autre, merci. –

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

Je pense que ceci est votre problème (ou l'un d'entre eux). Vous ne pouvez pas prendre la racine carrée d'un nombre négatif (et cela n'a pas d'importance si c'est -1 ou -99).

+1

En outre, la somme de deux carrés ne peut jamais être négative. Pas que vous pouvez vérifier de manière fiable l'égalité en utilisant ==, de toute façon. – aib

+0

OK, donc c'est inutile, mais pas un problème. – schnaader

+0

Je pensais que ça ne deviendrait jamais négatif ... en supprimant cette partie, alors. Je vous remercie. –

1

Ceci est probablement pas la source de votre erreur, mais cette fonction n'est pas tout à fait raison:

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

Cela renverra toujours un angle compris entre -pi/2 et + pi/2, et peut retourner un résultat incorrect si first.x - second.x est très faible et proche de 0, mais pas exactement 0. au lieu de cela, il suffit d'utiliser atan2:

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

atan2() retourne toute la gamme d'angles de -pi à + pi, et gère les bord des cas de manière appropriée. Cela ne vous affectera probablement pas puisque vous prenez juste le sin/cos de l'angle résultant. Vous le faites d'une manière très inefficace, cependant - vous appelez angleBetweenPoints() 8 (!) Fois lorsque le résultat est le même temps, et en prenant 4 sin() s et 4 cos() s. Vous pouvez ignorer toute la trigonométrie et utiliser la géométrie de triangles similaires pour obtenir les mêmes résultats.

+0

Merci, je n'ai pas travaillé avec l'objectif-C longtemps. Je l'ai changé pour atan2f. En outre, merci de souligner les appels répétés. –

Questions connexes