views:

1392

answers:

3

I have a set of balloons that I am trying to get to bounce off of each other like balls. When I start to move them and then detect collision, the routine for the collisions eventually returns a NAN for the velocity of the balloons. I end up with a position of something like x=270, y= -nan(0x400000). I've been looking at the code all day and I still can't find the error, any help would be appreciated. Here's the code:

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

}

}

Here's the functions written in c that are used for distance and the angle. I'm even making sure to never have a sqrt(-1) and division by 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));
}

}

+1  A: 

If uBalloon is an array your iteration should be between 0:(n-1).

E.g.

for (CurBalloon=0; CurBalloon < NumBalloons; ++CurBalloon)
{
  uBalloon[curBalloon] // blah
}
Andrew Grant
You should correct this to CurBalloon < NumBalloons.
schnaader
another one, thanks.
Bryan Cimo
+1  A: 
[...]
if ((deltaX*deltaX + deltaY*deltaY ) == -1) {
    return sqrtf(-.99);
} else {
[...]

I think this is your problem (or one of them). You can't take the square root of a negative number (and it doesn't matter if it's -1 or -.99).

schnaader
Also, sum of two squares can never be negative. Not that you can reliably check for equality using ==, anyway.
aib
OK, so this is unnecessary, but not a problem.
schnaader
I thought it might not ever go negative... deleting that part, then. Thank You.
Bryan Cimo
+1  A: 

This probably isn't the source of your error, but this function isn't quite right:

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

This will always return an angle between -pi/2 and +pi/2, and it may return an incorrect result if first.x - second.x is very small and close to 0, but not exactly 0. Instead, just use atan2:

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

atan2() returns the full range of angles from -pi to +pi, and handles the edge cases appropriately. This probably won't affect you since you're just taking the sin/cos of the resulting angle. You're doing so in a very inefficient manner, however -- you're calling angleBetweenPoints() 8 (!) times when the result is the same very time, and taking 4 sin()s and 4 cos()s. You could skip all of the trigonometry and just use the geometry of similar triangles to get the same results.

Adam Rosenfield
Thank You, I haven't been working with objective-C long. I changed it to atan2f. Also, thanks for pointing out the repeated calls.
Bryan Cimo