0

I'm creating a small 2D game and I want to detect collision between two PNG files. For this, I suppose I need to convert a surface to rect because I don't think surface can be used for collision detect. If you think about any other solutions to this than converting from surface to rect, let me know.

Error:

File "c:\Users\xxxx\Desktop\Projects\Games\game.py", line 44, in <module>
window.blit(kert, (1720, 0))
TypeError: argument 1 must be pygame.Surface, not pygame.Rect

Entire code (if it even matters):

# Importing pygame and random library:
import pygame, random

# Starting up the pygame module:
pygame.init()

# Variables:

# PNG FILES:
kert = pygame.image.load('veriscarykert.png').get_rect()
henry = pygame.image.load('veriscaryhentai.png').get_rect()

# FONT:
# Parameters - Font name; Font Size
font = pygame.font.SysFont('None', 48)
# TEXT: 
# Parameters - Text; Bool; RGB Value
text = font.render("CATCH THE SCARI KERT!!!", True, (0, 0, 0))

# Set the width and height of the pygame window
# Windowed
window = pygame.display.set_mode((1920,1020))

# Set the name for the pygame window:
pygame.display.set_caption('CATCH SCARI KERT!!')

# Define coordinates of the henry PNG file in X and Z:
henry_x = 540
henry_z = 540

# Variable for collision:
collide = kert.colliderect(henry)

# While loop
while True:

    # Set the window's colour with RGB value
    # In this case, I've chosen yellow as the colour.
    # Putting window.fill in the while loop removes trails of the moving PNG file 
    window.fill((255,255,0))

    # Apply the kert PNG file to the window:
    # PARAMETERS - Variable; Coordinates
    window.blit(kert, (1720, 0))

    # Apply the kert PNG file to the window:
    # PARAMETERS - Variable; Coordinates
    window.blit(henry, (henry_x, henry_z))

    # Apply text to the window:
    # PARAMETERS - Variable; Coordinates
    window.blit(text, (100, 300))

    # Variable for key presses:
    key = pygame.key.get_pressed()

    # If henry and kert collide
    if collide:
        # Define kert variable coordinates with the random module
        kert_x = random.randint(50, 1720)
        kert_z = random.randint(50, 900)

    # If the user presses the close button on the window's border:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            # Close the game

    # If W key is pressed
    if key[pygame.K_UP]:
        # Remove 5 from Z coordinates
        henry_z -= 5
    # If S key is pressed
    if key[pygame.K_DOWN]:
        # Add 5 to Z coordinates
        henry_z += 5
    # If A key is pressed
    if key[pygame.K_LEFT]:
        # Remove 5 from X coordinates
        henry_x -= 5
    # If D key is pressed
    if key[pygame.K_RIGHT]:
        # Add 5 to X coordinates
        henry_x += 5

    # Save changes
    pygame.display.update()
Static
  • 21
  • 4
  • "For this, I suppose I need to convert a surface to rect because I don't think surface can be used for collision detect." Python does not, generally speaking, transform objects to a different type in place. If you ask a Surface to give you the corresponding Rect, then the Surface still exists. It's just that your code only *named* the Rect for later usage, and forgot about the Surface (allowing it to be garbage-collected, unless Pygame keeps an internal reference). If you need both, then just have both: give a name to the surface, then ask for the Rect via that name, then name the Rect. – Karl Knechtel May 17 '22 at 15:53
  • Think carefully about what those types are. A Rect is *only* information about the dimensions and position of something, so that Pygame can do math to detect a collision. A Surface is *image data*, which obviously is needed in order to do the blitting. You want to do blitting (show the images) and also detect collisions, so you need both. (Keep in mind that, in some cases, you might want the collision to use a rect *not* determined by the corresponding image size. For example, if the image has a transparent border.) – Karl Knechtel May 17 '22 at 15:55
  • You may also find [gamedev.se] more useful for questions like this one. – Karl Knechtel May 17 '22 at 15:56
  • Separately: keep in mind that the point of collision detection is to detect *collisions*. I.e., not just intersections of static things, but a *change* from not-intersecting to intersecting, that happens because an object *moved*. That means, you have to *keep checking*, i.e., each time through the update loop, because things could have collided in the last frame. So calls like `.colliderect` need to be inside the loop. (You also need to get the Rects inside the loop; do you see why?) – Karl Knechtel May 17 '22 at 15:59

2 Answers2

0

pygame.image.load loads an image and creates a pygame.Surface. However get_rect() returns a pygame.Rect size of the Surface.. You have to create a Suraface not a Rect. Just remove get_rect():

kert = pygame.image.load('veriscarykert.png').get_rect() henry = pygame.image.load('veriscaryhentai.png').get_rect()

kert = pygame.image.load('veriscarykert.png')
henry = pygame.image.load('veriscaryhentai.png')

For the collision detection you have to create the bonding rectangle from the surface (see also How do I detect collision in pygame?):

collide = kert.colliderect(henry)

while True:
    # [...]

    kert_rect = kert.get_rect(topleft = (1720, 0))
    henry_rect = kert.get_rect(topleft = (henry_x, henry_z))
    collide = kert_rect.colliderect(henry_rect)

    # [...]
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
0

I had been using pygame for a year now.

pygame.image.load() is a type of pygame surface that can be connected with a rect for collision detection.

Always create a new rect per image

From

kert_surf = pygame.image.load('veriscarykert.png')
henry_surf = pygame.image.load('veriscaryhentai.png')

To

"""
CONSTANTS
- Includes Kert and Henry starting coordinates
"""
KERT_START = (1720, 0)
HENRY_START = (540, 540)

"""
For Kert and Henry make sure to always add an rect surface to enable collisions.

Include image starting position in the rect
"""
# Kert
kert_surf = pygame.image.load('veriscarykert.png')
kert_rect = kert_surf.get_rect(topleft=KERT_START)

# Henry
henry_surf = pygame.image.load('veriscaryhentai.png')
henry_rect = henry_surf.get_rect(topleft=HENRY_START)

I also refactored your code a little bit to be more readable and consistent but didn't stray too much from your coding style.

Added:

  • pygame Clock for more consistent FPS
  • Constants for rect's starting position
  • Refactored game loop for more consistent sequence of events
  • Changed Z axis to Y axis as pygame rect uses y axis

The code should work immediately by running it.

Here's the full code. Enjoy!

import pygame
import random

pygame.init()

"""
CONSTANTS
- Includes Kert and Henry starting coordinates
"""
KERT_START = (1720, 0)
HENRY_START = (540, 540)

"""
For Kert and Henry make sure to always add an rect surface to enable collisions

Include image starting position in the rect
"""
# Kert
kert_surf = pygame.image.load('veriscarykert.png')
kert_rect = kert_surf.get_rect(topleft=KERT_START)

# Henry
henry_surf = pygame.image.load('veriscaryhentai.png')
henry_rect = henry_surf.get_rect(topleft=HENRY_START)


# font:
# parameters - font name; font size
font = pygame.font.Font(None, 48)
# text:
# parameters - text; bool; rgb value
text = font.render("catch the scari kert!!!", False, (0, 0, 0))

# set the width and height of the pygame window
# windowed
window = pygame.display.set_mode((1920,1020))

# set the name for the pygame window:
pygame.display.set_caption('catch scari kert!!')

"""
Add clock for more consistent FPS
"""
clock = pygame.time.Clock()


while True:
    """
    Enable Game Quit
    """
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

    """
    Arrow Key Movement
    """
    key = pygame.key.get_pressed()
    if key[pygame.K_UP]:
        henry_rect.y-=20
    
    if key[pygame.K_DOWN]:
        henry_rect.y+=20

    if key[pygame.K_LEFT]:
        henry_rect.x-=20
    
    if key[pygame.K_RIGHT]:
        henry_rect.x+=20

    """
    Henry Collision with Kent 
    """
    if henry_rect.colliderect(kert_rect):
        kert_rect.x = random.randint(50,1720)
        kert_rect.y = random.randint(50,900)

    """
    Blit Images to Screen 
    """

    window.fill((255,255,0))
    window.blit(kert_surf,kert_rect)
    window.blit(henry_surf,henry_rect)
    window.blit(text, (100, 300))

    """
    Update Screen
    """
    pygame.display.update()
    clock.tick(60)
Knn_Zero
  • 11
  • 1
  • 2