I’m making an Asteroids game and to handle collisions between objects, I’m storing them in a vector. I then loop through the vector of objects, check them for collisions, and call their update functions. This works fine...ish. My problem is that very occasionally, for no apparent reason, I get NaNs appearing in some of my variables. What I don’t understand is how they can work at some times and not others.
1 2 3 4 5 6
for(std::vector<gameObject*>::iterator it=objects.begin(); it!=objects.end(); it++)//iterate through all the game objects
{
...
vx1 = (*it)->getXV(); vy1 = (*it)->getYV();//these are the functions that sometimes fail
...
}
I believe the problem lies with the getXV and getYV functions (which are functions returning floats for horizontal and vertical velocity respectively) but I cannot for the life of me work out why it works for about 90% of the time.
As for gameObjects, they are created and then a function called register adds them to the vector. This bit seems to work fine, I’ve used multiple cout statements all over the place to test things and I haven’t noticed anything unusual there.
Half of my problem is that I don’t know really what the error is. I’ve found that occasionally, xv will be NaN but I don’t know why. There doesn’t seem to be any pattern to the errors that I can see: a specific value or range doesn’t seem to produce the error each time which makes me believe it might be to do with the vector or pointers. Am I dereferencing the pointer correctly?
We can't really help you further if you don't post the relevant bits (whatever calculations are used to update the object's position based on its velocity (I'm assuming the velocity is fixed, as you said), object creation and object deletion, and insertion/removal from the vector).
I’m sorry, it’s quite a large chunk of code which would require a fairly in-depth explanation so I’m trying to keep it as light as possible. I guess that’s not helping xD
in the gameObject’s update function:
x+=xv;
y-=yv;
update is then called in the iteration:
(*it)->update();
The velocity is being updated based on 2D collisions. Here is the code for the collisions (it’s probably very inefficient but I’d like to get it to work first before I try anything else).
void game::update(float f)
{
for(std::vector<gameObject*>::iterator it=objects.begin(); it!=objects.end(); it++)
{
for(std::vector<gameObject*>::iterator itt=objects.begin(); itt!=objects.end(); itt++)
{
if(it!=itt) //make sure we don’t check an object against itself
{
double dx = 0, dy = 0, d = 0, dt = 0; //initialise some variables
dx = (*itt)->getX()-(*it)->getX(); //distance in x
dy = (*itt)->getY()-(*it)->getY(); //distance in y
d = sqrt(dx*dx + dy*dy); //pythagorean distance between the two objects
if(d<((*it)->getRadius()+(*itt)->getRadius())) //if the distance is less than the sum of the bounding circles
{
double ax = 0, ay = 0, vx1 = 0, vy1 = 0, vx2 = 0, vy2 = 0; //initialise more variables
ax = dx/d; ay = dy/d; //get the normals
vx1 = (*it)->getXV(); vy1 = (*it)->getYV(); //get the velocities for object 1
vx2 = (*itt)->getXV(); vy2 = (*itt)->getYV(); //get the velocities for object 2
double n1 = vx1*ax + vy1*ay; //more normalisation
double n2 = vx2*ax + vy2*ay;
dt = (((*it)->getRadius()+(*itt)->getRadius()) - d)/(n1-n2); //how much the objects bounding circles overlap
double x1 = (*it)->getX(), y1 = (*it)->getY(); //positions
double x2 = (*itt)->getX(), y2 = (*itt)->getY();
(*it)->setX(x1-=(vx1*dt)); (*it)->setY(y1-=(vy1*dt)); //move the objects apart so that d = sum of bounding circles
(*itt)->setX(x2-=(vx2*dt)); (*itt)->setY(y2-=(vy2*dt));
double va1=(n1), vb1=(-n1);
double va2=(n2), vb2=(-n2);
double vaP1=va1 + (1+ELASTICITY)*(va2-va1)/(1+((*it)->getSize()/((*itt)->getSize()))); //solve 1D collisions (I’m using a constant for size, which is returned by getSize()
double vaP2=va2 + (1+ELASTICITY)*(va1-va2)/(1+((*itt)->getSize()/((*it)->getSize())));
vx1=vaP1*ax-vb1*ay; vy1=vaP1*ay+vb1*ax; //the new velocities after the collision
vx2=vaP2*ax-vb2*ay; vy2=vaP2*ay+vb2*ax;
(*it)->setXV(vx1); (*it)->setYV(vy1); //set the velocities
(*itt)->setXV(vx2); (*itt)->setYV(vy1);
x1 = (*it)->getX(); y1 = (*it)->getY(); //get the positions
x2 = (*itt)->getX(); y2 = (*itt)->getY();
(*it)->setX(x1+=(vx1*dt)); (*it)->setY(y1+=(vy1*dt)); //adjust for the overlap given earlier
(*itt)->setX(x2+=(vx2*dt)); (*itt)->setY(y2+=(vy2*dt));
}
}
}
(*it)->update(f); //f is the framerate
(*it)->wrapScreen(); //a function for making the objects wrap around the screen
}
}