I see that this is an older question, but I'd like to share my own solution to this problem, as it's part of a recent project of mine and I just cleared out some collision detection that was exactly like yours, more or less. I had two queues of 'good-guys' and 'bad-guys' and every frame I would do this:
#old code!! not great!! :(
for goodguy in goodqueue:
for badguy in badqueue:
if goodguy.rect.colliderect(badguy.rect):
goodguy.got_hit()
badguy.got_hit()
#i don't recommend this approach!! :(
Even with my simple game, which might have one Player object, 3 - 4 'good guy' Bullets it fired, comparing it against the 3/5/7 bad guys in the badqueue and their Bullets they fire at random intervals… that is a lot of iterations that we don't need!
This is the current state of my project's hit detection: it's a little more code, but it will scale so much better and flat out ignores collisions that aren't happening.
for obj in GAME.allqueue:
obj.update()
hit_list = pygame.sprite.spritecollide(obj, GAME.allqueue, False)
if not hit_list:
pass
elif obj in GAME.goodqueue:
for otherobj in hit_list:
if otherobj in GAME.badqueue:
obj.got_hit()
otherobj.got_hit()
I'll explain what's going on here.
First, the loop calls obj.update()
, which does normal game logic-type stuff; moves sprites, determines if they're fired, etc etc.
The next line, hit_list = pygame.sprite.spritecollide(obj, GAME.allqueue, False)
, tells PyGame to generate a list of all the things that obj
is colliding with in GAME.allqueue
, which is an instance of pygame.sprite.Group
(as I would imagine your carlist
is). This is fantastic, because now we just have a list of what's actually colliding with that object.
The next two lines: if not hit_list: pass
basically tell the game if the hit_list
is empty, don't do anything collision-related and continue on with the game loop. The line if not a_list
is a Pythonic idiom which is basically the same as if len(a_list) == 0
, or "if this list is empty", or whatever you want to call it. Basically - this is where the game decides if it should even bother with collision detection, or move on to the next important step.
The rest of the code may be a bit situational and not apply to your game/simulation, as my game basically works to avoid 'friendly fire' between both good guys AND bad guys. (It basically makes sure two colliding objects are in separate queues, so only 'good guy meets bad guy' collisions are processed) However -- In your situation, I believe you'd be able to make use of pygame.sprite.spritecollide
in a similar fashion.
for car in carlist: #let's get a list of everything THIS car is colliding with!
cars_hit_list = pygame.sprite.spritecollide(car, carlist, False) #False tells PyGame NOT to auto-kill the whole list of results!
if not cars_hit_list:
pass #if the cars_hit_list has no length, do nothing!
else: #this is assuming you just want all cars to crash…
for crashedcar in cars_hit_list:
handle_the_crashes() #whatever you actually do to crash the cars
In my humble opinion -- as long as you're using the pygame.Sprite
objects to handle your sprites and the various Group
s they belong to, using the list you get back from pygame.sprite.spritecollide
will be more satisfying than just iterating over every possible combination of potential collisions to see if they are occurring.