4

Hello I tried to create simple 2D platformer game but when i tried to check collision between 2 objects it fails even when those two objects do not collide. I used pygame.sprite.collide_rect but it returns 1 everytime it checks collision. I don't really know why this happens. Please help me. Here is code: main.py

import pygame
from lib import player
level=['PPPPPPPPPPP',
       'P  P',
       'PPPPPPPPPPP',
       '',
       '',
       'PPPPPPPPPPP']


from pygame.locals import (
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
    K_ESCAPE,
    KEYDOWN,
    QUIT,
)

white=(255,255,255)
green=(0,255,0)
blue=(0,0,255)
red=(255,0,0)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600

pygame.init()

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

rb=player.Red_Block()
player1 = player.Player(screen, rb)


running = True



while running:
    platform=[]
    screen.fill((0, 0, 0))
    row_c=0
    for row in level:
        counter=0
        for item in row:
            if item == 'P':
                rb=player.Red_Block()
                platform.append(rb)
                screen.blit(rb.surf, (counter*31, row_c*31))
            counter+=1
        row_c+=1
    player1.set_platform(platform)

    for event in pygame.event.get():
        if event.type == KEYDOWN:

            if event.key == K_ESCAPE:
                running = False
            if event.key == K_DOWN:
                player1.move_down()
            if event.key == K_LEFT:
                player1.move_left()
            if event.key == K_RIGHT:
                player1.move_right()
            if event.key == K_UP:
                player1.move_up()

        elif event.type == QUIT:
            running = False
    #player1.draw()

    #screen.fill((0, 0, 0))

    player1.gravity()
    screen.blit(player1.surf, (player1.x, player1.y))



    pygame.display.flip()

lib.player.py

import pygame
from lib.block import *
white=(255,255,255)
green=(0,255,0)
blue=(0,0,255)
red=(255,0,0)


class Player(pygame.sprite.Sprite):
    def __init__(self, screen, block):
        super(Player, self).__init__()
        self.platform=None
        self.screen=screen
        self.block=block
        self.surf = pygame.Surface((20, 30))
        self.surf.fill(blue)
        self.x=120
        self.y=120
        self.rect = self.surf.get_rect()
    def move_up(self):
        self.y-=5
    def move_down(self):
        self.y += 5
    def move_left(self):
        self.x -= 5
    def move_right(self):
        self.x += 5
    def check_col(self, s1, s2):
        col = pygame.sprite.collide_rect(s1, s2)
        return col
    def set_platform(self, platform):
        self.platform = platform
    def gravity(self):
        for item in self.platform:
            if pygame.sprite.collide_rect(item, self) == 1:
                print(pygame.sprite.collide_rect(item, self))
            if pygame.sprite.collide_rect(item, self) == 0:
                print(pygame.sprite.collide_rect(item, self))
                self.y -= 1


lib.block.py

import pygame
white=(255,255,255)
green=(0,255,0)
blue=(0,0,255)
red=(255,0,0)

class Red_Block(pygame.sprite.Sprite):
    def __init__(self):
        super(Red_Block, self).__init__()
        self.surf = pygame.Surface((32, 32))
        self.surf.fill(red)
        self.rect = self.surf.get_rect()

Sorry for my bad english

1 Answers1

3

A pygame.Surface doesn't have a position, it just have a size. get_rect() returns a rectangle, which always starts at (0, 0). You've to set the position of the rectangle.

You've to verify if the player does not collides with any block:

items = [item for item in self.platform if pygame.sprite.collide_rect(item, self)]
if not any(items):
    # [...]

Skip the attributes .x and .y and use the .rect.x and .rect.y instead.

class Player(pygame.sprite.Sprite):
    def __init__(self, screen, block):
        super(Player, self).__init__()
        self.platform=None
        self.screen=screen
        self.block=block
        self.surf = pygame.Surface((20, 30))
        self.surf.fill(blue)
        self.rect = self.surf.get_rect(topleft = (120, 120))
    def move_up(self):
        self.rect.y-=5
    def move_down(self):
        self.rect.y += 5
    def move_left(self):
        self.rect.x -= 5
    def move_right(self):
        self.rect.x += 5
    def check_col(self, s1, s2):
        col = pygame.sprite.collide_rect(s1, s2)
        return col
    def set_platform(self, platform):
        self.platform = platform
    def gravity(self):
        items = [item for item in self.platform if pygame.sprite.collide_rect(item, self)]
        if not any(items):
            self.rect.y += 1

Note, the .rect attribute of Red_Block doesn't have a position, too:

rb=player.Red_Block()
rb.rect.topleft = (counter*31, row_c*31)

Furthermore it is sufficient to create the list of blocks (platform) once:

platform=[]
for row_c, row in enumerate(level):
    for counter, item in enumerate(row):
        if item == 'P':
            rb=Red_Block()
            rb.rect.topleft = (counter*31, row_c*31)
            platform.append(rb)
player1.set_platform(platform)

running = True
while running:

    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
            if event.key == K_DOWN:
                player1.move_down()
            if event.key == K_LEFT:
                player1.move_left()
            if event.key == K_RIGHT:
                player1.move_right()
            if event.key == K_UP:
                player1.move_up()
        elif event.type == QUIT:
            running = False

    screen.fill((0, 0, 0))

    for rb in platform:
       screen.blit(rb.surf, rb.rect.topleft) 
    player1.gravity()
    screen.blit(player1.surf, player1.rect.topleft)

    pygame.display.flip()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Ok I'm total noob at pygame , so how can i set a position of `.rect` – ToggleMountain Nov 26 '19 at 17:21
  • Ok now something even more strange happens. First thing that happens is the black window apears than after 5 seconds i think the rectangles appear and player is below the level how can i fix that? And btw thanks for extending comment :D – ToggleMountain Nov 26 '19 at 17:35
  • Oh sorry i didn't paste rest of the code. But it still doesn't work :(. – ToggleMountain Nov 26 '19 at 17:43