Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've been looking for articles or tutorials on this and I can't seem to find any, so I thought I'd ask here. I've created a bullet class in my game that is added and removed through a list. If I'm going to make these bullets work the way I want them to I need to be able to do two things:

One, I need to check if the bullets are colliding with each other and then remove the two bullets that are colliding. I've tried doing it by updating the bullet list with a for statement and then checking for collision with another for statement, but that occasionally crashes the game.

Two, I need to be able to check how far away every other bullet in the list is from the current one.

So how can I go about doing this?

share|improve this question

2 Answers 2

up vote 6 down vote accepted

The crash you are getting is probably because you are removing objects from the list while iterating through it. This will modify the Count of the list and the iterator will try to access elements that no longer exist.

The solution is to use a second list to which you add the objects that must be deleted.

for(int i = 0; i < bulletList.Count - 1; i++)
{
    for(int j = i + 1; j < bulletList.Count; j++)
    {
        if(bulletList[i].CollidesWith(bulletList[j])
        {
            bulletsColliding.Add(bulletList[i]);
            bulletsColliding.Add(bulletList[j]);
        }
    }
}

for(int i = 0; i < bulletsColliding.Count; i++)
{
    bulletList.Remove(bulletsColliding[i]);
}
bulletsColliding.Clear();

Unfortunately, the problem with this is that you can get duplicates of bullets in your bullets colliding list if a bullet is colliding with more than one bullet at a time. Using C# lists the Remove function will only return false though.

Using flags to set the bullets to Alive or not can be a good idea to stop you from having to instanciate a Bullet if dead ones aleady exist. I would however just 'move' the bullets into a second list which is neither Draw()'n nor Update()'d, and move them back when you need to create a new bullet, and the list isn't empty.

You must be very careful though that the Bullet instance is properly reset before you re-insert it into the working list.


To check the distance between bullets, you can use Pythagoras' theorem. In 2D :

float Distance(Bullet a, Bullet b)
{
    float xDistance = b.x - a.x;
    float yDistance = b.y - a.y;

    float sqDistance = (xDistance * xDistance) + (yDistance * yDistance);

    return Math.sqrt(sqDistance);
}

In very time-critical sections, it is common to use squared positions of objects and not perform the square-root operation, as it is quite expensive.

share|improve this answer
    
Use the right data-structure for the job. When bulletList is large, the first code listing loops over the list many more times than it needs to (remember that bulletList.Remove() is an O(n) function..). Making bulletList a Dictionary<int, Bullet> would fix this at the cost of more memory, without having to change any code. -- We could also use a linked-list and remove collisions while we iterate, at the possible cost of correctness - if three bullets collide at once, only two will be removed. –  BlueRaja - Danny Pflughoeft Jul 29 '11 at 17:31
1  
@BlueRaja - Danny Pflughoeft : Reading the comments from the other answer "there can only be ten bullets in the game at one time" I think Lists are probably sufficient. –  Jonathan Connell Jul 29 '11 at 18:10
    
I agree, if there's only 10 it's not even worth thinking about optimizing –  BlueRaja - Danny Pflughoeft Jul 29 '11 at 18:19

I would use an array of Bullets (with Bullet value type), with an "Alive" flag to "add/remove" bullets without generating too much garbage. You can iterate over the array and simply skip bullets that are not currently used (make sure to clear data before deactivating them).

The first point is tricky. If you check every bullet against all other bullets and repeat, you're going to have way too many checks. You could have a spatial partitioning system and move from there.

Is it a "bullet hell"-type of game?

share|improve this answer
    
No, it's a puzzle game and I want the bullets to act sort of like magnets when they're done. So if two bullets with the same charge get close they push each other away and if two bullets with opposite charges get close they draw each other in and destroy each other. Also, I don't think there will be a problem with the number of checks because there can only be ten bullets in the game at one time. –  IronGiraffe Jul 29 '11 at 10:45
    
Why did you call them "bullets"? –  FxIII Jul 29 '11 at 10:51
    
@IronGiraffe, then we'd be looking at 100 checks at most (if I got the math right, but who knows), so I'm going to assume you're going to be okay with just iterating over bullets. –  Raine Jul 29 '11 at 10:51
2  
It's worth noting that you only have to check the bullets that come after the current bullet, since the previous bullets you've checked have already tested against the current bullet. So each of your inner loops should be smaller than the last. This means that, assuming ten bullets, on the first one you have to check the other 9. On the second bullet, you don't have to check the first one anymore or itself, so you only need 8 checks. And so on. By my calcs, that's only 45 checks! And that's not very many. :) –  Richard Marskell - Drackir Jul 29 '11 at 11:47
    
Drackir is right, thanks @Drackir –  Raine Jul 29 '11 at 12:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.