#### Archived

This topic is now archived and is closed to further replies.

# help with stl's and sphere colliding

This topic is 5776 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi guys. Im gonna explain this a simple as possible. I have two stl lists. one holds X number of asteroids the other holds x number of missles. I have coded it so that when I fire a missle and it reaches a certain point, that specific link on that missle list is .erase()'d I want to tie this in with the asteroid link list so if the rocket and asteroid collide (sphere collision being used) then they both die. My problem is tieing the two link lists in together to check for this. Whether or not this is a good method is another arguement, but if you can enlighten me with some help, i would most certainly appreciate it. here is the code for running through the lists, straight from my draw() function (this is opengl)

for(astWalker = asteroidList.begin(); astWalker != asteroidList.end(); astWalker++)
{	// now update each animation for each rocket in the list!

astWalker->Animate(elapsedSeconds);
astWalker->Draw();
}

// now we traverse our rockets link list, this one DRAWS the rockets

if(rocketList.size() > 0)	// dont bother unless we have something to play with!

{
for(rokWalker = rocketList.begin();	rokWalker != rocketList.end(); rokWalker++)
// now update each animation for each rocket in the list!

{
rokWalker->Animate();

// now we traverse our asteroid link list, this one TESTS FOR COLLISIONS

for(astWalker = asteroidList.begin(); astWalker != asteroidList.end(); astWalker++)

// now check if the collision spheres radius total is <=

// the length of the distance between the asteroid and the missle

{
float radi = (astWalker->size + rokWalker->size);
float dist = (astWalker->position - rokWalker->position).Length();

{	// if so, kill the asteroid AND the rocket, and continue

asteroidList.erase(astWalker);
rocketList.erase(rokWalker);

}

}	// COOL!

if (rokWalker->death())		// has this rocket hit its distance?

rocketList.erase(rokWalker++);	// if so, kill it.

}

}	// that was easy


in my main.h file elsewhere I have the following declarations

using namespace std;	// not quite sure what this does, however its essential for link lists

list<CRocket> rocketList;				// initialize a rocket link list

list<CAsteroid> asteroidList;			// initialize an asteroid link list

list<CRocket>::iterator rokWalker;		// asteroid list walker

list<CAsteroid>::iterator astWalker;	// asteroid list walker


but thats not the hassle. I get strange results, crashes....you name it, but no accurate sphereical collisions. If you can help me recode this, I would severly appreciate it. PS: Everything was fine until I had this sphere stuff old code was:

for(astWalker = rocketList.begin(); astWalker != rocketList.end(); astWalker++)

// now update each animation for each rocket in the list!

{
astWalker->Animate(elapsedSeconds);
astWalker->draw();
}

// now we traverse our rockets link list

if(rocketList.size() > 0)	// dont bother unless we have something to play with!

{
// ok we declare an iterator to be something to "walk" through the list

// starting at the beginning, finishing at the last node (rocket) on the list

for(rokWalker = rocketList.begin(); rokWalker != rocketList.end(); rokWalker++)

// now update each animation for each rocket in the list!

{
rokWalker->Animate();
if (rokWalker->death())		// has this rocket hit its distance?

rocketList.erase(rokWalker++);	// if so, kill it.

}
}	// that was easy


which as you can see was fine. The new trick is to implement the sphere collision. Thats where im struggling to tie the functions together. Cheers ~~~~~~~~~~~~~~~~~~~~~~~~~ http://on.to/oni [edited by - fatherjohn666 on December 1, 2002 7:22:38 AM]

##### Share on other sites
Well, I think I see the problem here...

quote:
Original post by fatherjohn666

  // now we traverse our rockets link list, this one DRAWS the rocketsif(rocketList.size() > 0)	// dont bother unless we have something to play with!{	for(rokWalker = rocketList.begin();	rokWalker != rocketList.end(); rokWalker++)				// now update each animation for each rocket in the list!	{			rokWalker->Animate(); 					// now we traverse our asteroid link list, this one TESTS FOR COLLISIONS		for(astWalker = asteroidList.begin(); astWalker != asteroidList.end(); astWalker++)							// now check if the collision spheres radius total is <=			// the length of the distance between the asteroid and the missle		{				float radi = (astWalker->size + rokWalker->size);			float dist = (astWalker->position - rokWalker->position).Length();							if (  dist <  radi)			{	// if so, kill the asteroid AND the rocket, and continueasteroidList.erase(astWalker);rocketList.erase(rokWalker);								}		}	// COOL!

When you call list::erase(pos) it returns an iterator to the next item in the list. This because the element of the list that pos used to point to is now gone (along with the linked list pointers that allow you to advance pos to the next item).

That means that when you have a collision and go back to the top of the for loop, astWalker++ accesses some random garbage where an asteroid used to be and uses that to work out where the next asteroid is. This is not a good thing . What you need to do instead is use the return value of erase(pos) as the next iterator when an asteroid/rocket is erased, and use ++pos otherwise. Something like this should do it:

  astWalker = asteroidList.begin();while(astWalker != asteroidList.end()){   if(/*snip collision testing code*/)   {      astWalker = erase(astWalker);   }   else   {      ++astWalker;   }}

You'll have to be pretty careful when you erase the rocket too. If you do it on the first collision, subsequent collsion checks will crash. It would probably be easiest to just count the number of asteroids a rocket has collided with and then erase the rocket if the count is greater than zero.

  for(rokWalker = rocketList.begin(); rokWalker != rocketList.end(); rokWalker++)	// now update each animation for each rocket in the list!{		rokWalker->Animate(); 	if (rokWalker->death())		// has this rocket hit its distance?		rocketList.erase(rokWalker++);	// if so, kill it.}

Here you got lucky . Using the postincrement operator means that rokWalker gets incremented to point to the next rocket, but the old value is returned. When erase returns, you already have an iterator to the next item in the list. Unfortunately, it gets incremented again by the for loop, so one rocket is skipped after
each rocket that dies. At least it doesn't crash though .

PS: "using namespace std;" lets you refer to things defined in "namespace std" without having to fully qualify their name. Everything in the standard library is in the std namespace, so you need to use the name std::list<whatever> rather than list<whatever>, unless you have "using namespace std;" somewhere before the list<whatever> line. Google should have plenty of hits for "C++ namespace" if you want to find out more.

EDIT: Put the tags in the right place this time...

[edited by - Krunk on December 1, 2002 9:11:49 AM]

##### Share on other sites
Excellent,good explanation, makes sense, unfortunately I cant try it atm (at work on a non gl laptop) but i will try it later and let you know

thanks

~~~~~~~~~~~~~~~~~~~~~~~~~

http://on.to/oni

1. 1
2. 2
3. 3
Rutin
18
4. 4
JoeJ
14
5. 5

• 14
• 10
• 23
• 9
• 42
• ### Forum Statistics

• Total Topics
632635
• Total Posts
3007559
• ### Who's Online (See full list)

There are no registered users currently online

×