I am having trouble with getting collisions to work with my platformer in PyGame

Viewed 69

I am making a platformer in PyGame which will involve there being an obstacle which the player has to maneuver through. I've set up how to make the base 'floor' of the game but I am having trouble getting the collisions to work properly when it comes to actual 'boxes' or obstacles. The code is split over 4 files which I'll upload but the bulk of the code is in the main game loop file and the file which contains the class for the player itself. The collision logic happens within the player class and is run as a function in the main loop. I've tried an assortment of methods in getting the collisions to work but something has always gone wrong. I want it so that jumping on the obstacle will cause the player to stand on it and run head-on into the obstacle won't allow the character to pass. Although I don't have the logic for standing on the obstacles, I do have some logic for preventing the player from running through them. But even then there are bugs. For example, running into the right side of an obstacle moves me over to the left side when it should be 'pushing back' against the player and negating his xVel to prevent further movement past the obstacle. There a couple more bugs with running into the obstacles which you can find out by running the program but any help with improving the horizontal collisions and developing the vertical collisions would be much appreciated. Main Game Loop:

import pygame
import character as c
import levels
pygame.init()



WINWIDTH = 1200
WINHEIGHT = 700


win = pygame.display.set_mode((WINWIDTH,WINHEIGHT))
pygame.display.set_caption('Game')



all_sprites = pygame.sprite.Group()
terrainSprites = pygame.sprite.Group()
obstacleSprites = pygame.sprite.Group()
player = c.Player(win, WINWIDTH, WINHEIGHT)
all_sprites.add(player)
terrainSprites.add(levels.level1Terrain)
obstacleSprites.add(levels.level1Obstacles)

mainloop = True

clock = pygame.time.Clock()
while mainloop:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            mainloop = False




    all_sprites.update()
    terrainSprites.update()
    obstacleSprites.update()
    player.collision(player.rect.x, player.rect.y)
    win.fill((0,0,0))
    terrainSprites.draw(win)
    obstacleSprites.draw(win)
    pygame.draw.rect(win, (255, 0, 0), obstacleSprites.sprites()[0].rect, 2)
    pygame.draw.rect(win, (255, 0, 0), player.rect, 2)  # (player.rect.x + 4, player.rect.y + 5, 43, 50)
    all_sprites.draw(win)
    pygame.display.flip()
    clock.tick(60)
pygame.quit()

Character File Which Contains the Player Class and the Collision Logic:

import pygame

class Player(pygame.sprite.Sprite):
    def __init__(self, surface, WINWIDTH, WINHEIGHT):
        pygame.sprite.Sprite.__init__(self)
        self.framecounter = 1
        self.images = []
        self.idleframes = []
        self.surface = surface
        self.width = 40
        self.height = 60
        self.WINWIDTH = WINWIDTH
        self.WINHEIGHT = WINHEIGHT
        self.xVel = 5
        self.yVel = 5
        self.jumpActive = False
        self.jumpCounter = 12
        self.walking = False
        self.grounded = True
        #LOAD WALKCYCLE
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/1.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/2.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/3.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/4.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/5.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/6.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/7.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/8.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/9.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/10.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/11.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/12.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/13.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/14.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/15.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/16.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/17.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/18.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/19.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/20.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/21.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/22.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/23.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/24.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/25.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/26.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/27.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/28.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/29.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/30.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/31.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/32.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/33.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/34.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/35.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/36.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/37.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/38.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/39.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/40.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/41.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/42.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/43.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/44.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/45.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/46.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/47.png"))
        self.images.append(pygame.image.load("D:/PythonProjects/game/Assets/WalkCycleLeft - Copy/48.png"))

        # LOAD JUMP UP - Idx. 48
        self.images.append(pygame.image.load("D:\PythonProjects\game\Assets\Pixel Adventure 1\Free\Main Characters\Virtual Guy\Jump (32x32).png"))

        # LOAD JUMP FALL - Idx. 49
        self.images.append(pygame.image.load("D:\PythonProjects\game\Assets\Pixel Adventure 1\Free\Main Characters\Virtual Guy\Fall (32x32).png"))


        #LOAD IDLE FRAMES - Idx. >49
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/1.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/1.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/1.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/1.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/2.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/2.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/2.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/2.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/3.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/3.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/3.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/3.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/4.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/4.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/4.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/4.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/5.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/5.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/5.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/5.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/6.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/6.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/6.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/6.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/7.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/7.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/7.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/7.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/8.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/8.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/8.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/8.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/9.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/9.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/9.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/9.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/10.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/10.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/10.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/10.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/11.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/11.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/11.png"))
        self.idleframes.append(pygame.image.load("D:/PythonProjects/game/Assets/Idle/11.png"))





        self.framecounter = 1
        self.idlecounter = 1
        self.image = self.images[self.framecounter]
        self.image = pygame.transform.scale(self.image, (50,50))
        self.rect =  self.image.get_rect()
        self.rect.x = 200
        self.rect.y = 640
        self.rect.width = 50
        self.rect.height = 50
        self.facing = None

    def update(self):

        self.walking = False
        keys = pygame.key.get_pressed()

        if keys[pygame.K_a]:
            self.rect.x -= self.xVel
            self.walkcycle()
            self.facing = 'left'
            self.walking = True
        elif keys[pygame.K_d]:
            self.rect.x += self.xVel
            self.walkcycle('right')
            self.facing = 'right'
            self.walking = True
        else:
            self.walking = False

        if self.jumpActive == False and self.grounded == True:
            if keys[pygame.K_SPACE]:
                self.jumpActive = True
        else:
            if self.jumpCounter >= -12:
                self.jumpUPAnim()
                neg = 1
                if self.jumpCounter < 0:
                    self.fallAnim()
                    neg = -1
                self.rect.y -= int((self.jumpCounter ** 2) * 0.25 * neg)
                self.jumpCounter -= 1
            else:
                self.jumpCounter = 12
                self.jumpActive = False
        if self.rect.x >= (self.WINWIDTH - 40):
            self.rect.x = int(self.WINWIDTH - 40)
        elif self.rect.x <= 0:
            self.rect.x = 0
        if self.rect.y >= (self.WINHEIGHT - 55):
            self.rect.y = int(self.WINHEIGHT - 55)
            self.grounded = True
        elif self.rect.y <= 0:
            self.rect.y = 0


        self.idleAnim(self.facing)
        self.gravity()
    def walkcycle(self, facing = None):
        self.image = self.images[self.framecounter]
        self.image = pygame.transform.scale(self.image, (50,50))
        if facing == 'right':
            self.image = pygame.transform.flip(self.image, True, False)

        self.framecounter += 1
        if self.framecounter == 48:
            self.framecounter = 1
    def jumpUPAnim(self):
        self.image = self.images[48]
        self.image = pygame.transform.scale(self.image, (50,50))
        if self.facing == 'left':
            self.image = pygame.transform.flip(self.image, True, False)
    def fallAnim(self):
        self.image = self.images[49]
        self.image = pygame.transform.scale(self.image, (50,50))
        if self.facing == 'left':
            self.image = pygame.transform.flip(self.image, True, False)
    def idleAnim(self, facing):
        if self.jumpActive == False and self.walking == False:
            self.image = self.idleframes[self.idlecounter]
            self.image = pygame.transform.scale(self.image, (50,50))
            if facing == 'left':
                self.image = pygame.transform.flip(self.image, True, False)
            self.idlecounter += 1
            if self.idlecounter == 44:
                self.idlecounter = 1
    def collision(self, store_x, store_y):
        from main import terrainSprites
        from main import obstacleSprites
        old_pos = self.rect.x, self.rect.y
        for i in terrainSprites:
            if pygame.sprite.spritecollide(self, terrainSprites, False):
                if self.rect.y < i.rect.top:
                    self.rect.bottom = i.rect.top
                    return True
                else:
                    return False
        for i in obstacleSprites:

            if pygame.sprite.spritecollide(self, obstacleSprites, False):
                if self.rect.bottom < i.rect.top:
                    self.yVel = 0
            else:
                self.yVel = 5
                self.rect.y = store_y
            if pygame.sprite.spritecollide(self, obstacleSprites, False):
                if self.rect.right < i.rect.left:
                    self.xVel = 0
            else:
                self.xVel = 5
                self.rect.x = store_x
    def gravity(self):
            self.rect.y += self.yVel

Entire project folder containing all the files including the terrain file which has the class for generating terrain, the obstacle file, which has the class for generating obstacles, and the levels file which builds a level using the obstacle and terrain classes. The project also includes assets: https://drive.google.com/drive/folders/13XirZjMSAB_p3TJFFDFYtRG-oIE0XjAz?usp=sharing

1 Answers

PyGame makes it very easy for us to check collides of one object with another, according to my understanding you wanna know if one thing collides with another, if that's the case I have a good answer with the following code below I'll be using firstRect as whatever you wanna check that collided with the secondRect

if firstRect.colliderect(secondRect):
    # Do stuff

I really hope this is what you wanted if not you can just tell me and I'll try to give a better answer

Happy coding - BSK - SK Studio

Related