1

So I'm a beginner at making games with python PyGame and I am trying to write a function to detect collision. Here is the function I currently have:

def collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
    rect_list = [h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4]
    for rectangle in rect_list:
        if rect.rect.colliderect(rectangle.rect):
            return True
    return False

This is the full code of my game_functions.py:

import pygame, sys, random

def collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
    rect_list = [h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4]
    for rectangle in rect_list:
        if rect.rect.colliderect(rectangle.rect):
            return True
    return False



def rect_movement(settings, event, rect, name, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                  h1w1_4):
    if settings.selected_block == str(name):
        if event.key == pygame.K_RIGHT and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                                                   h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_x < 300:
                rect.img_x += 75
        elif event.key == pygame.K_LEFT and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1,
                                                                    h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_x > 0:
                rect.img_x -= 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_x += 75
        elif event.key == pygame.K_UP and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                                                  h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_y > 0:
                rect.img_y -= 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_y += 75
        elif event.key == pygame.K_DOWN and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1,
                                                                    h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_y < 200:
                rect.img_y += 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_y -= 75


def square_movement(settings, event, rect, name, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                    h1w1_4):
    if settings.selected_block == str(name):
        if event.key == pygame.K_RIGHT and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                                                   h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_x < 100:
                rect.img_x += 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_x -= 75
        elif event.key == pygame.K_LEFT and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1,
                                                                    h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_x > 20:
                rect.img_x -= 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_x += 75
        elif event.key == pygame.K_UP and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                                                  h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_y > 50:
                rect.img_y -= 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_y += 75
        elif event.key == pygame.K_DOWN and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1,
                                                                    h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_y < 300:
                rect.img_y += 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_y -= 75
            else:
                print('You win!')


def sml_square_movement(settings, event, rect, name, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2,
                        h1w1_3, h1w1_4):
    if settings.selected_block == str(name):
        if event.key == pygame.K_RIGHT:
            if rect.img_x < 200:
                rect.img_x += 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                                                   h1w1_1, h1w1_2, h1w1_3, h1w1_4):
                    rect.img_x -= 75

        elif event.key == pygame.K_LEFT:
            if rect.img_x > 20:
                rect.img_x -= 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_x += 75

        elif event.key == pygame.K_UP:
            if rect.img_y > 50:
                rect.img_y -= 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_y += 75

        elif event.key == pygame.K_DOWN:
            if rect.img_y < 300:
                rect.img_y += 75
                if collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                                       h1w1_4):
                    rect.img_y -= 75


def rect_h1_movement(settings, event, rect, name, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2,
                     h1w1_3, h1w1_4):
    if settings.selected_block == str(name):
        if event.key == pygame.K_RIGHT and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                                                   h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_x < 150:
                rect.img_x += 75
        elif event.key == pygame.K_LEFT and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1,
                                                                    h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_x > 0:
                rect.img_x -= 75
        elif event.key == pygame.K_UP and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                                                  h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_y > 0:
                rect.img_y -= 75
        elif event.key == pygame.K_DOWN and not collision_detection(rect, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1,
                                                                    h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
            if rect.img_y < 300:
                rect.img_y += 75


def check_events(settings, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        elif event.type == pygame.MOUSEBUTTONUP:
            settings.selected_block = random.choice(['h1w1_1', 'h1w1_2', 'h1w1_3',
                                                     'h1w1_4', 'h1w2_1', 'h2w1_1',
                                                     'h2w1_2', 'h2w1_3', 'h2w1_4',
                                                     'h2w2_1'])

        elif event.type == pygame.KEYDOWN:
            # h2w1_1 movement
            rect_movement(settings, event, h2w1_1, 'h2w1_1', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1,
                          h1w1_2, h1w1_3, h1w1_4)

            # h2w1_2 movement
            rect_movement(settings, event, h2w1_2, 'h2w1_2', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1,
                          h1w1_2, h1w1_3, h1w1_4)

            # h2w1_3 movement
            rect_movement(settings, event, h2w1_3, 'h2w1_3', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1,
                          h1w1_2, h1w1_3, h1w1_4)

            # h2w1_3 movement
            rect_movement(settings, event, h2w1_4, 'h2w1_4', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1,
                          h1w1_2, h1w1_3, h1w1_4)

            # h2w2 movement
            square_movement(settings, event, h2w2_1, 'h2w2_1', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1,
                            h1w1_2, h1w1_3, h1w1_4)

            # h1w2 movement
            rect_h1_movement(settings, event, h1w2_1, 'h1w2_1', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1,
                             h1w1_2, h1w1_3, h1w1_4)

            # h1w1_1 movement
            sml_square_movement(settings, event, h1w1_1, 'h1w1_1', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                h1w1_1, h1w1_2, h1w1_3, h1w1_4)

            # h1w1_2 movement
            sml_square_movement(settings, event, h1w1_2, 'h1w1_2', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                h1w1_1, h1w1_2, h1w1_3, h1w1_4)

            # h1w1_3 movement
            sml_square_movement(settings, event, h1w1_3, 'h1w1_3', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                h1w1_1, h1w1_2, h1w1_3, h1w1_4)

            # h1w1_4 movement
            sml_square_movement(settings, event, h1w1_4, 'h1w1_4', h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1,
                                h1w1_1, h1w1_2, h1w1_3, h1w1_4)


def update_screen():
    pygame.display.flip()

My main program:

import pygame

from py_files.settings import Settings

# Shape imports
from py_files.h2w1_1 import rect2hw1_1
from py_files.h2w1_2 import rect2hw1_2
from py_files.h2w1_3 import rect2hw1_3
from py_files.h2w1_4 import rect2hw1_4
from py_files.h2w2_1 import rect2hw2_1
from py_files.h1w2_1 import rect1hw2_1
from py_files.h1w1_1 import rect1hw1_1
from py_files.h1w1_2 import rect1hw1_2
from py_files.h1w1_3 import rect1hw1_3
from py_files.h1w1_4 import rect1hw1_4

import py_files.game_functions as gf


def run_game():
    pygame.init()

    # Start classes
    settings = Settings()

    display = pygame.display.set_mode((settings.screen_width, settings.screen_height))
    h2w1_1 = rect2hw1_1(display)
    h2w1_2 = rect2hw1_2(display)
    h2w1_3 = rect2hw1_3(display)
    h2w1_4 = rect2hw1_4(display)
    h2w2_1 = rect2hw2_1(display)
    h1w2_1 = rect1hw2_1(display)
    h1w1_1 = rect1hw1_1(display)
    h1w1_2 = rect1hw1_2(display)
    h1w1_3 = rect1hw1_3(display)
    h1w1_4 = rect1hw1_4(display)

    while True:
        # Blit images
        h2w1_1.blitme()
        h2w1_2.blitme()
        h2w1_3.blitme()
        h2w1_4.blitme()
        h2w2_1.blitme()
        h1w2_1.blitme()
        h1w1_1.blitme()
        h1w1_2.blitme()
        h1w1_3.blitme()
        h1w1_4.blitme()

        # Updating
        gf.check_events(settings, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4)
        gf.update_screen()
        display.fill(settings.bg_color)


run_game()

And I have 10 separate programs for all the rectangles. Here is what one of them look like (for the other 9, I just changed the image and the self.x, self.y variables):

h1w1.py:

import pygame

class rect1hw1_1():
    def __init__(self, screen):
        self.screen = screen
        self.img_x = 75
        self.img_y = 225

    def blitme(self):
        img = pygame.image.load('py_files/images/h1w1.png')
        self.screen.blit(img, (self.img_x, self.img_y))
        self.rect = img.get_rect()

And I also have an image for the default state of my game: The Game Image

What this is supposed to do, is to check if the selected sprite (rect variable) collides with any of those other variable rectangles (h2w1_1, h2w1_2, h2w1_3, ...). But with this code, now, none of my sprites can move. Why is that? And how can I fix it?

Thank you in advance!

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
GGberry
  • 929
  • 5
  • 21

1 Answers1

1

Use pygame.Rect.collidelist to test whether a rectangle collides with one of a list of rectangles:

rect_list = [h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4]
if rect.rect.colliderect(tile_rects) >= 0:
    # [...]

pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument. For example, the center of the rectangle can be specified with the keyword argument center. These keyword argument are applied to the attributes of the pygame.Rect before it is returned (see pygame.Rect for a full list of the keyword arguments).

Create a rectangle with the new location and do the collision test. Only change the location if no collision is detected:

def rect_movement(settings, event, rect, name, h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3,
                  h1w1_4):
    if settings.selected_block == str(name):
        
        testrect = rect.get_rect(topleft = (rect.img_x, rect.img_y))
        if event.key == pygame.K_LEF and testrect.x > 0:
            testrect.x -= 75
        elif event.key == pygame.K_RIGH and testrect.x < 300:
            testrect.x += 75
        elif event.key == pygame.K_UP and testrect.y > 0:
            testrect.y -= 75
        elif event.key == pygame.K_DOWN  and testrect.y < 200:
            testrect.y += 75

        rect_list = [h2w1_1, h2w1_2, h2w1_3, h2w1_4, h2w2_1, h1w2_1, h1w1_1, h1w1_2, h1w1_3, h1w1_4]
        if not testrect.collidelist(rect_list):
            rect.img_x, rect.img_y = testrect.topleft
Rabbid76
  • 202,892
  • 27
  • 131
  • 174