1

How can i make a collision system in the simplest way in pygame, without using classes. I've been trying for a long time and none of the ways works, in my last attempt the code was like this: (Sorry if it's wrongly written, I'm a beginner in all this)

import pygame
from pygame.locals import *
from sys import exit

pygame.init()

G = 9.807 # GRAVITY

screen = pygame.display.set_mode((400, 400))
time = pygame.time.Clock()

y_speed = 0
playersize = [20, 20]
playerpos = [0, 0]

def move(dx):
    playerpos[0] += dx

    if player.colliderect(block):
        if dx > 0:
            playerpos[0] -= player.right - block.left
        if dx < 0:
            playerpos[0] -= player.left - block.right
               
while 1:
    time.tick(30)
    screen.fill((255,255,255))
    player = pygame.draw.rect(screen, (255,0,0), (playerpos[0], playerpos[1], playersize[0], playersize[1]))
    block = pygame.draw.rect(screen, (0,0,0), (100, 380, 20, 20))

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()
        if event.type == KEYDOWN:
            if event.key == K_SPACE or event.key == K_UP or event.key == K_w:
                if playerpos[1] == 380:
                    y_speed = -5
                    time = pygame.time.Clock()
                else:
                    pass
    
    T = time.get_time() / 1000
    F = G * T
    y_speed += F
    playerpos[1] += y_speed
    
    if playerpos[1] >= 380:
        playerpos[1] = 380
        y_speed = 0
        time = pygame.time.Clock()
    else:
        pass
    
    keys = pygame.key.get_pressed()
    if keys[K_a] or keys[K_LEFT]:
        move(-5)
    if keys[K_d] or keys[K_RIGHT]:
        move(5)
        
    pygame.display.update()
ogustavxs
  • 13
  • 2

1 Answers1

1

You must create a pygame.Rect object with the current position of the player before the collision test. If the player hits the block from the left, the player`s right must be set by the left of the block. If the player hits the block from the right, the player's right must be set by the left of the block:

def move(dx):
    playerpos[0] += dx

    player = pygame.Rect((playerpos[0], playerpos[1], playersize[0], playersize[1]))
    if player.colliderect(block):
        if dx > 0:
            player.right = block.left
            playerpos[0] = player.left
        if dx < 0:
            player.left = block.right
            playerpos[0] = player.left

You can add the collision for the y-direction in a similar way. However, you must perform the collision detection in y direction before the collision detection in x direction:

def move(dx, dy):

    playerpos[1] += dy
    player = pygame.Rect((playerpos[0], playerpos[1], playersize[0], playersize[1]))
    if player.colliderect(block):
        if dy > 0:
            player.bottom = block.top
            playerpos[1] = player.top

    playerpos[0] += dx
    player = pygame.Rect((playerpos[0], playerpos[1], playersize[0], playersize[1]))
    if player.colliderect(block):
        if dx > 0:
            player.right = block.left
            playerpos[0] = player.left
        if dx < 0:
            player.left = block.right
            playerpos[0] = player.left

Complete and working example:

import pygame
from pygame.locals import *
from sys import exit

pygame.init()

G = 9.807 # GRAVITY

screen = pygame.display.set_mode((400, 400))
time = pygame.time.Clock()

y_speed = 0
playersize = [20, 20]
playerpos = [0, 0]

def move(dx, dy):

    playerpos[1] += dy
    player = pygame.Rect((playerpos[0], playerpos[1], playersize[0], playersize[1]))
    if player.colliderect(block):
        if dy > 0:
            player.bottom = block.top
            playerpos[1] = player.top

    playerpos[0] += dx
    player = pygame.Rect((playerpos[0], playerpos[1], playersize[0], playersize[1]))
    if player.colliderect(block):
        if dx > 0:
            player.right = block.left
            playerpos[0] = player.left
        if dx < 0:
            player.left = block.right
            playerpos[0] = player.left

block = pygame.Rect(150, 330, 20, 20)
ground_y = 350

run = True            
while run:
    time.tick(30)
    for event in pygame.event.get():
        if event.type == QUIT:
            run = False
        if event.type == KEYDOWN:#
            if event.key == K_SPACE or event.key == K_UP or event.key == K_w:
                if playerpos[1] == ground_y - playersize[1]:
                    y_speed = -5

    keys = pygame.key.get_pressed()
    move_left = keys[K_a] or keys[K_LEFT]
    move_right = keys[K_d] or keys[K_RIGHT]
    x_speed = (move_right - move_left) * 5
    
    T = time.get_time() / 1000
    F = G * T
    y_speed += F
    move(x_speed, y_speed)
    if playerpos[1] >= ground_y - playersize[1]:
        playerpos[1] = ground_y - playersize[1]
        y_speed = 0
        
    screen.fill((255,255,255))
    pygame.draw.rect(screen, "gray", (0, ground_y, 400, 400-ground_y))
    pygame.draw.rect(screen, (255,0,0), (playerpos[0], playerpos[1], playersize[0], playersize[1]))
    pygame.draw.rect(screen, (0,0,0), block)
    pygame.display.update()

pygame.quit()
exit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174