[Python] Collision detecting not working properly for rects in pygame [duplicate]

Discussão em 'Python' iniciado por Stack, Maio 14, 2025.

  1. Stack

    Stack Membro Participativo

    I was trying to make my first app in python as a simple plataformer to understand a little about pygame, but I eventually encountered an issue. In my code, for some reason, when I added sub-pixel positioning to make jumping smooth, the collision detectition stopped working. I got it to work, but only by removing the float value in my position dict with the char properties which made (I don't know why) the jump stop halfway, probably because the velocity was too low, so that when i divided by 60 (the framerate), I rounded down to 0 and didn't move. I bugtested and the velocity stayed correct the intire way through. This is my code:

    import pygame

    pygame.init()
    window = pygame.display.set_mode((1600, 800))
    pygame.display.set_caption("Testing pygame!")

    clock = pygame.time.Clock()

    window_size = {"x": pygame.display.get_window_size()[0], "y": pygame.display.get_window_size()[1]}

    player = {
    "position": {"x": 0, "y": 0},
    "size": {"x": 100, "y": 100},
    "velocity": {"x": 0, "y": 0},
    "color": (30, 30, 150),
    "standing": None
    }

    gravity = 100 # pixels/s

    plataforms = [
    {
    "rect": pygame.Rect(600, 0, 100, 50),
    "color": (0, 0, 0)
    }
    ]

    running = True

    while running:
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    running = False
    if event.type == pygame.KEYUP: # key released
    if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
    if player["velocity"]["x"] > 0:
    player["velocity"]["x"] = 0
    elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
    if player["velocity"]["x"] < 0:
    player["velocity"]["x"] = 0
    if event.type == pygame.KEYDOWN: # key pressed
    if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
    player["velocity"]["x"] = 50
    elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
    player["velocity"]["x"] = -50
    elif event.key == pygame.K_SPACE or event.key == pygame.K_w or event.key == pygame.K_UP:
    if player["standing"] == True:
    player["velocity"]["y"] = 100
    player["standing"] = False

    window.fill((150, 150, 150)) # reset display

    for plataform in plataforms:
    pygame.draw.rect(window, plataform["color"], (
    plataform["rect"].x,
    window_size["y"] - plataform["rect"].y - plataform["rect"].h,
    plataform["rect"].w,
    plataform["rect"].h
    ))

    pygame.draw.rect(window, player["color"], (
    player["position"]["x"],
    window_size["y"] - player["position"]["y"] - player["size"]["y"],
    player["size"]["x"],
    player["size"]["y"]
    ))

    for plataform in plataforms: # handle plataform collisions
    rect = plataform["rect"]
    pos = player["position"]
    size = player["size"]
    velocity = player["velocity"]

    if pygame.Rect(
    pos["x"],
    window_size["y"] - pos["y"] - size["y"],
    size["x"],
    size["y"]
    ).colliderect(rect): # check if player is colliding with plataform
    if pos["x"] + size["x"] >= rect.x or rect.x + rect.w >= pos["x"]:
    if rect.x <= pos["x"] + size["x"] <= rect.x + (rect.w / 2): # check if player is touching the left side
    if velocity["x"] > 0:
    velocity["x"] = 0
    pos["x"] = rect.x - size["x"]
    elif rect.x + rect.w >= pos["x"] >= rect.x + (rect.w / 2): # check if player is touching the right side
    if velocity["x"] < 0:
    velocity["x"] = 0
    pos["x"] = rect.x + rect.w
    elif pos["y"] + size["y"] >= rect.y or rect.y + rect.h >= pos["y"]:
    if rect.y <= pos["y"] + size["y"] <= rect.y + (rect.h / 2): # check if player is touching the bottom
    velocity["x"] = 0
    pos["y"] = rect.y - size["y"]
    elif rect.y + rect.h >= pos["y"] >= rect.y + (rect.h / 2): # check if player is touching the top
    velocity["x"] = 0
    pos["y"] = rect.y + rect.h
    player["standing"] = True

    if player["position"]["x"] < 0: # handle window border collisions
    player["position"]["x"] = 0
    elif player["position"]["x"] + player["size"]["x"] > window_size["x"]:
    player["position"]["x"] = window_size["x"] - size["x"]
    if player["position"]["y"] < 0:
    player["position"]["y"] = 0
    player["velocity"]["y"] = 0
    player["standing"] = True
    elif pos["y"] + size["y"] >= window_size["y"]:
    player["velocity"]["y"] = 0
    player["position"]["y"] = window_size["y"] - player["size"]["y"]

    if player["position"]["y"] == 0:
    player["standing"] = True
    elif player["velocity"]["y"] != 0:
    player["standing"] = False

    print(player["velocity"])
    player["position"]["x"] += player["velocity"]["x"] / 60
    player["position"]["y"] += player["velocity"]["y"] / 60

    if not player["standing"]:
    player["velocity"]["y"] -= gravity / 60

    pygame.display.flip() # refresh display
    clock.tick(60) # cap fps to 60

    pygame.quit()

    pygame.Rect(0, 0, 100, 100).move


    The changes I have mentioned before that solved half and broke half were making in the player dictionnary the position and size into one right away with pygame.Rect(), which rounded the values (I assume it was because of that), and stopped the jump from working mid-way through. Apart from that, for some reason in the x-dimension physics, player["position"]["x"] += player["velocity"]["x"] / 60 player["position"]["y"] += player["velocity"]["y"] / 60 I could not use player["character"].move() or .move_ip(), (I made the name of the player Rect "character" inside it). If anyone knows how to solve, I'd be glad. PS: I'd be glad if you didn't use a little more advanced stuff (e.g: classes), as I'm still going to learn that. Thanks.

    Continue reading...

Compartilhe esta Página