0

I am using a for loop combined with .colliderect() for collision detection while attempting to make a game using pygame, the loop gets too slow with ~340 wall Rectangles, I was wondering if it could be faster somehow because it severely effects the game play loop?

I have tried using coordinate points on different places on every wall but only works if you're moving certain amounts of pixels at a time and every time you half the movement speed it quadruples the amount of coordinate points you save.

#disregard indent, this is all in an update function that is called every time that a player decides to move.
        self._old_position = self.position
        PlayerRectangle = pygame.Rect(self.position[0]+ x,self.position[1]+y,16,16)
        cwd = os.getcwd()
        tmxData = load_pygame(cwd+"\\Maps\\TestfileMap.tmx")
        movement = True
        for obj in self.walls:                   
                if(pygame.Rect(obj[0],obj[1],16,16).colliderect(PlayerRectangle)):
                        movement = False
                        self.move_back()
                else:
                        continue
        if movement:
                self.position[0] += x
                self.position[1] += y
                self.stats["position"]=self.position
                self.rect.topleft = self.position
                self.feet.midbottom = self.rect.midbottom

The provided code works, however it is too slow, I was wondering if there is a different method in collision detection or if there is a way to make what is shown faster, it bogs down things greatly. Thank you

EDIT:

So the solution was basically that I had load_pygame that ran literally every time it looped simply take out the line that does that and it clears things up a lot more, for further optimization change the line that makes a Rect for each object and just use a list of Rects that are already constructed, this limits function calls.

  • You don't show all the code there, but there is a `...load...` function called with a filename - if that is done in the middle of the action of a game it is a **major NO!**. Everything touching the filesystem must be done when setting up a scene, or on a separate thread. – jsbueno May 06 '19 at 15:42
  • Other than that, w[ – jsbueno May 06 '19 at 15:43
  • @jsbueno That's a built in pygame/pytmx function, removing that did help tremendously. the only reasons I use pygame_load is to interpret layers and extract specific objects from it. –  May 06 '19 at 17:46

1 Answers1

0

Without a minimal working example it is tough to give assertive advice.

As I stated in the comments, there is a spurious call to a "load_pygame" function that seems to read file data inside this code - that alone could be the cause of your slowdown. Moreover, the data read is not used in the collision detection.

The other advice I't have is to let your walls rectangles pre-calculated in a sprite group, instead of creating new rectangles for all walls in every check with: pygame.Rect(obj[0],obj[1],16,16).colliderect(PlayerRectangle)). then you can use the sprite method "spritecollideany" - https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollideany - that should optimize the rectangle-collision verification.

(This will also require your Player object to be a Sprite if it is not already).

jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • Turns out the problem was with the fact that I was using load_pygame in the middle of the code, if you were wondering load_pygame is a built in function of pytmx, specifically pytmx.util_pygame. It was an artifact from a function i copied from another function that I used to parse the collision layer. The rectangles for the walls are all pre calculated, I was simply using it odd. I will check into the spritecollideany function though. Thanks –  May 06 '19 at 17:48