0

How do I make a rectangle check for collisions with a lot of different rectangles? I am making a platformer, and I got collision working with one platform, but no idea how to add multiple.

I do not know how to add more rectangles via a variable. My only other idea is to make a bunch of rectangles with different names, and individually check each one. That wouldn't work very efficiently if I were to put like 30 rectangles in my level, and it would look like spaghetti.

I have searched online for info on how to do this, but I am finding completely unrelated problems!

Here's the code if relevant. Edit: No longer snipped, now the entire code. Sorry if its long, 88 lines.

import pygame
import math

# Defining important variables
pygame.init()
keys = pygame.key.get_pressed()
clock = pygame.time.Clock()

# LEVEL DESIGN
ground_rect = []
ground_rect.append(pygame.Rect(0, 200, 200, 50))
ground_rect.append(pygame.Rect(0, 200, 300, 100))

# Screen stuff
bg_color = 204, 255, 220
screen_y = 360
screen_x = 480
screen = pygame.display.set_mode((screen_x, screen_y))

# Player's img and start coordinates.
player_img = pygame.image.load("player.png").convert()
player_y = 0
player_x = 0
player_y_velocity = 0
player_x_velocity = 0
coyote = 0


def pic(img, x, y):
    screen.blit(img, (x + 0, y + 0))


def main():
    screen.fill(bg_color)
# Get the variables global
    global player_y             # Y position of player
    global player_x             # X position of player
    global player_y_velocity    # Y velocity of player
    global player_x_velocity    # X velocity of player
    global coyote               # Checks if you are on ground, and gives a bit of extra frames to jump if not.

# Inputs
    if pygame.key.get_pressed()[pygame.K_UP] and coyote > 0:
        player_y_velocity = -9
        coyote = 0

# This makes your jump lower when you release!
    if not pygame.key.get_pressed()[pygame.K_UP] and player_y_velocity < -1:
        player_y_velocity = -1

# Move left/right when pressing left/right!
    player_x_velocity = (pygame.key.get_pressed()[pygame.K_RIGHT] - pygame.key.get_pressed()[pygame.K_LEFT]) * 2.5

# Velocity effects
    player_y_velocity += 0.4
    player_y_velocity = min(player_y_velocity, 10)
    player_x += player_x_velocity
    player_y += player_y_velocity
    coyote -= 1
# Rectangles
    player_rect = pygame.Rect(player_x, player_y, 32, 32)

    # !!Collision!!
    for i in range(10):
        if player_rect.colliderect(ground_rect):
            player_y -= 1
            player_y_velocity = 0.5
            coyote = 4
            player_rect = pygame.Rect(player_x, player_y, 32, 32)
    # Draw stuff (pic is a function I made to shorten the blit)
    pic(player_img, player_x, player_y)
    pygame.draw.rect(screen, (64, 0, 0), ground_rect)


# Main script
while True:
    main()
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            break
    if player_y > 376:
        pygame.quit()
        break
    clock.tick(60)

Edit: I am going to include the way I am trying to make a list of ground rectangles as well as the error message I am getting.

# LEVEL DESIGN
ground_rect = []
ground_rect.append(pygame.Rect(0, 200, 200, 50))
ground_rect.append(pygame.Rect(0, 200, 300, 100))

Here's the error the IDE I am using, Pycharm is throwing at me.

Expected type 'Union[Rect, RectType, tuple[int, int, int, int], list[int], tuple[Union[tuple[float, float], list[float], Vector2, Vector2], Union[tuple[float, float], list[float], Vector2, Vector2]], list[Union[tuple[float, float], list[float], Vector2, Vector2]], _HasRectAttribute]', got 'list[Rect]' instead

Here's the traceback log:

Traceback (most recent call last):
  File "C:\Users\Matt\PycharmProjects\lettherebechaos\main.py", line 77, in <module>
    main()
  File "C:\Users\Matt\PycharmProjects\lettherebechaos\main.py", line 65, in main
    if player_rect.colliderect(ground_rect):
TypeError: Argument must be rect style object
Plide
  • 15
  • 5
  • Use a list variable for your rectangles. – Alain T. Aug 24 '21 at 02:31
  • Hi when I try to make a list I get this error: Expected type 'Union[Rect, RectType, tuple[int, int, int, int], list[int], tuple[Union[tuple[float, float], list[float], Vector2, Vector2], Union[tuple[float, float], list[float], Vector2, Vector2]], list[Union[tuple[float, float], list[float], Vector2, Vector2]], _HasRectAttribute]', got 'list[Rect]' instead – Plide Aug 24 '21 at 02:48
  • Please show how you are creating that list. Also show us in your code snippet which rectangles you are checking collision with. I only see ground_rect. Lastly, could you explain why you have a for loop that runs 10 times when checking for collision? – wxker Aug 24 '21 at 03:03
  • I am using a for loop that checks if your touching ground and moves you up one pixel at a time because that's the only method I know. It's probably bad, but I don't know how else to do it. – Plide Aug 24 '21 at 05:03

1 Answers1

1

As mentioned by Alian, you have to use a list to store multiple rects (or anything at all if you want more than just a few). Then you can iterate through that list and check for collisions. Here is a quick fresh example since your code does not provide anything related to it.

import pygame

#make a list and add 30 rects in it
rects = []
for x in range(5):
    for y in range(6):
        rects.append(pygame.Rect(x * 50 + 10, y * 50 + 10, 40, 40))
    

pygame.init()
screen = pygame.display.set_mode((260, 310))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill((255, 255, 255))

    #go through all the rects and check for collision
    for rect in rects:
        color = (255, 0, 0)
        if (rect.collidepoint(pygame.mouse.get_pos())):
            color = (0, 255, 0)
        pygame.draw.rect(screen, color, rect)
            
    pygame.display.update()