So I'm writing a game. Here's how the collision detection works; there's an invisible grid, and objects (or, rather, their references) are added and removed from cells based on where they are. Collision comparisons are only done between objects in the same cell.
The references are stored in a Python set
that is owned by each cell. It has to be a set. When a collision is detected, it's stored in a Collision
object with three attributes; the two objects that collided and the time the collision occurred. When all collisions are accounted for, they're sorted by time, then processed.
This is the loop that individual cells use to check for collisions;
#grid.collisions is a list of recorded collisions, and self.objects is the set
#of objects currently in this cell.
for i in self.objects:
for j in self.objects:
if id(i) != id(j) and pygame.sprite.collide_rect(i, j):
grid.collisions.append(Collision(i, j))
The problem is, this compares the same two objects twice; if we had a set {1, 2, 3, 4}
, we'd be comparing (1, 2)
and (2, 1)
. Not only that, but these duplicate comparisons are being added into the total list of collisions and thereby breaking the entire system!
I know that I can't index sets, which means I can't do something like for j in range(i, len(self.objects))
where i
and j
are both integers. How can I get around this limitation to make sure that two objects in the same set are not compared twice? I can't remove the objects in these sets; they are only to be removed if the object leaves the grid cell.
Since these collisions are being handled every frame, I would prefer to avoid creating new objects (the real code doesn't create new Collisions
as the sample does, I just simplified it for readability). I could just remove duplicate comparisons, but to compare every collision to every other would be a lot of overhead.