Where should my collision take place?

Started by
3 comments, last by EJH 14 years, 2 months ago
Hi! I'm working on a project in Python with Pygame which involves character movement and collision with different class objects. Does collision checking belong in each object's update() step, or is it better to clog up the game's main loop with a ton of for-loop collision checking for each object against every other? The 2nd option basically would look like this:

# check collision between character and mines
for mine in mines:
     if mine.rect.colliderect(character.rect):
          # destroy mine
          # damage player

# check collision between character and bullets
for bullet in bullets:
     if bullet.rect.colliderect(character.rect):
          # destroy bullet
          # damage player


Is there a way to put this into OOP so that during each object's update() step it can check collision between any object it EXPECTS to collide with? If I have even 5 objects, I'm going to have a LOT of collisions to check for which is going to QUICKLY clutter up my main game loop. -1st object checking collision against remaining 4 objects -2nd object checking collision against remaining 3 objects -3rd object checking collision against remaining 2 objects etc = n(n-1) / 2 Can you help me fix this mess and shed some light on common programming practices?
Advertisement
I realized collision will only happen when something is moving..
Should I put the collision code for what an object may collide with into it's move() function, so that it can check for collision before completing the move?

If I go this route and create a move() function, what is the purpose of the update() function? Should I have all move() code in the beginning of update(), and remove the move() function altogether?

Collision should take place in the main loop.

Say you have rectA and rectB that are game objects that can both move and collide. if you only check rectA for collision against rectB in rectA's move function, there could still be a collision occuring if rectA is not moving but rectB is moving.

Edit: Your main loop isn't going to get too cluttered. Collision should only be checked for when an object is on screen.
Quote:Original post by Kada
Does collision checking belong in each object's update() step, or is it better to clog up the game's main loop with a ton of for-loop collision checking for each object against every other?

For small games, both will work, but for larger-scale games, you'll want to make a separate module for collision checking/handling. When you're using a physics engine you're doing exactly that.

Quote:If I have even 5 objects, I'm going to have a LOT of collisions to check for which is going to QUICKLY clutter up my main game loop.

-1st object checking collision against remaining 4 objects
-2nd object checking collision against remaining 3 objects
-3rd object checking collision against remaining 2 objects
etc = n(n-1) / 2

That's not a lot just yet - but you're right, it's not a very scalable approach. However, for a small game with only a handful of objects, it's no big deal. And, as you noticed, you don't need to check any object against any other: only perform relevant checks, and only for moving objects.

Quote:If I go this route and create a move() function, what is the purpose of the update() function? Should I have all move() code in the beginning of update(), and remove the move() function altogether?

If your movement code is complicated, it makes sense to put it in a function of it's own. What stops you from calling utility functions from within an update() function? :)

Quote:Original post by X Abstract X
Edit: Your main loop isn't going to get too cluttered. Collision should only be checked for when an object is on screen.

Not necessarily: bullets could still hit enemies outside the screen. Depends on what you want.


For a game with only few distinct object types, I'd do the collision checks in the main loop, with a few for-loops:
# Note that mines, rockets, bullets and so on are all projectiles:for projectile in projectiles:    if player.collidesWith(projectile):        projectile.applyDamageTo(player)# Check player versus enemy collisions# Check player bullets versus enemies


Another approach would be to have a world object that keeps track of these objects (which is often a good idea anyway) and to give the player and enemies a reference to it. They can then ask this world object if they're colliding with a bullet or with another game object.

As for keeping the number of checks down, read up on grids or quadtrees - data structures that are often used for spatial culling.
Create-ivity - a game development blog Mouseover for more information.
Clearly, this will vary widely between games, but if possible, I prefer when everything is neat passes.

- AI pass (every object decides where it wants to go)
- physics pass (every object moves)
- collision pass (collide and resolve collisions between all objects)

You'll probably want a separate module for each one of those.


This topic is closed to new replies.

Advertisement