Shokhrukh Valiev
Shokhrukh Valiev

Reputation: 107

Why am i getting Type errors when i am trying to check for collision and how can i fix it?

I am a Beginner in Python and i was making a simple 2D game in Pygame. I am almost done except for the collision checking with the pygame.Rect function. I am trying to check for collision with car2 and car under the comment "collision detecting" but i am getting -- TypeError: Invalid rectstyle argument. I researched for quite a while for this but i just am not able to utilize it in my code. I would appreciate if someone helped fix this problem.

import pygame
import random
import math


pygame.init()


black = (0, 0, 0)

screen_width = 600
screen_length = 800
screen = pygame.display.set_mode((screen_length, screen_width))
clock = pygame.time.Clock()
FPS = 60

icon = pygame.image.load('car.png')
pygame.display.set_icon(icon)

#game caption
pygame.display.set_caption("Car game")




#Main car
car = pygame.image.load('car.png')
carX = 370
carY = 470 
carX_change = 0

#second car
car2 = pygame.image.load('car2.png')
car2_rect = car.get_rect()
car2_X = random.randint(200, 600)
car2_Y = random.randint(-50, 0)
car2Y_speed = 13


#road side trees
tree1Img = pygame.image.load('tree1.png')
tree1_X = 70
tree1_Y = 30

tree2Img = pygame.image.load("tree2.png")
tree2_X = 700
tree2_Y = 300


tree3Img = pygame.image.load("tree3.png")
tree3_X = 70
tree3_Y = 400

tree4Img = pygame.image.load("tree4.png")
tree4_X = 700
tree4_Y = 50



#game functions
def car1(x, y):
    screen.blit(car, car_rect, (x, y))

def car_2(x, y):
    global car2_Y
    global car2_X
    screen.blit(car2, car2_rect, (x, y))
    car2_Y += car2Y_speed
    if car2_Y > screen_length:
        car2_X = random.randint(200, 545)
        car2_Y = random.randint(-50, 0)   


def tree1(x, y):
    global tree1_Y
    screen.blit(tree1Img, (x, y))
    tree1_Y += 10
    if tree1_Y >= screen_width:
        tree1_Y = -50


def tree2(x, y):
    global tree2_Y
    screen.blit(tree2Img, (x, y))
    tree2_Y += 10
    if tree2_Y >= screen_width:
        tree2_Y = -50


def tree3(x, y):
    global tree3_Y
    screen.blit(tree2Img, (x, y))
    tree3_Y += 10
    if tree3_Y >= screen_width:
        tree3_Y = -50


def tree4(x, y):
    global tree4_Y
    screen.blit(tree4Img, (x, y))
    tree4_Y += 10
    if tree4_Y >= screen_width:
        tree4_Y = -50

# 1st Road marker's movement
rectangleX = 426
rectangleY = 100
def roadmarker_move():
    global rectangleY
    if running == True:
        rectangleY += 10
    if rectangleY == 610:
        rectangleY = -50


#2nd road marker's movement
rectangle2_X = 426
rectangle2_Y = 410
def roadmarker2_move():
    global rectangle2_Y
    if running == True:
        rectangle2_Y += 10
    if rectangle2_Y == 610:
        rectangle2_Y = -50





#Main game loop
running = True
while running:
    screen.fill((119, 118, 110))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                carX_change = 48
            if event.key == pygame.K_LEFT:
                carX_change = -48

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                carX_change = 0
        carX += carX_change



    #drawing Road lines
    pygame.draw.line(screen, black, (639, 0), (639, 600), 10)
    pygame.draw.line(screen, black, (200, 0), (200, 600), 10)

    
    #drawing the 1st road markers
    rectangle = pygame.draw.rect(screen, black, (rectangleX, rectangleY, 15, 80))
    roadmarker_move()

    #drawing the 2nd road markers
    rectangle = pygame.draw.rect(screen, black, (rectangle2_X, rectangle2_Y, 15, 80))
    roadmarker2_move()

    #setting boundries
    if carX <= 170:
        carX = 170
    elif carX >= 547:
        carX = 547

    #collision detecting
    car_rect = car.get_rect()
    car_rect.topleft = (carX, carY)
    car_rect.move_ip((carX_change, 0))

    car2_rect = car2.get_rect()
    car2_rect.topleft = (car2_X, car2_Y)
    car2_rect.move_ip((car2Y_speed, 0))

    if ( car_rect.colliderect(car2_rect) ):
        print( "car hit tree" )


    car1(carX, carY)
    car_2(car2_X, car2_Y)
    tree1(tree1_X, tree1_Y)
    tree2(tree2_X, tree2_Y)
    tree3(tree3_X, tree3_Y)
    tree4(tree4_X, tree4_Y)
    clock.tick(FPS)
    pygame.display.update()

pygame.quit()

Upvotes: 1

Views: 74

Answers (1)

Rabbid76
Rabbid76

Reputation: 211136

The name of the attribute is topleft rather than top_left. See pygame.Rect.

Furthermore, move_ip has to be applied to the pygame.Rect object rather than to the Surface:

car.move_ip((carX_change, 0))

car_rect.move_ip((carX_change, 0))

Finally car_rect(x, y) makes not any sens at all. It is sufficient to pass a tuple with the position of the car to the method blit in the function car1:

screen.blit(car, car_rect(x, y))

screen.blit(car, (x, y))

respectively in the function car_2

screen.blit(car2, car2_rect, (x, y))

screen.blit(car2, (x, y))

To improve the collision you have to ensure that the collision rectangle reflects the actual position of the cars. You wrongly move the collision rectangles. Remove this lines of code and do the collision test after the cars have been moved:

car1(carX, carY)      # <--- INSERT
car_2(car2_X, car2_Y) # <--- INSERT

car_rect = car.get_rect()
car_rect.topleft = (carX, carY)
#car_rect.move_ip((carX_change, 0)) <--- DELETE

car2_rect = car2.get_rect()
car2_rect.topleft = (car2_X, car2_Y)
#car2_rect.move_ip((car2Y_speed, 0)) <--- DELETE

#car1(carX, carY)       <--- DELETE
#car_2(car2_X, car2_Y)  <--- DELETE

Complete example:

import pygame
import random
import math


pygame.init()


black = (0, 0, 0)

screen_width = 600
screen_length = 800
screen = pygame.display.set_mode((screen_length, screen_width))
clock = pygame.time.Clock()
FPS = 60

icon = pygame.image.load('car.png')
pygame.display.set_icon(icon)

#game caption
pygame.display.set_caption("Car game")


#Main car
car = pygame.image.load('car.png')
carX = 370
carY = 470 
carX_change = 0

#second car
car2 = pygame.image.load('car2.png')
car2_rect = car.get_rect()
car2_X = random.randint(200, 600)
car2_Y = random.randint(-50, 0)
car2Y_speed = 13


#road side trees
tree1Img = pygame.image.load('tree1.png')
tree1_X = 70
tree1_Y = 30

tree2Img = pygame.image.load("tree2.png")
tree2_X = 700
tree2_Y = 300


tree3Img = pygame.image.load("tree3.png")
tree3_X = 70
tree3_Y = 400

tree4Img = pygame.image.load("tree4.png")
tree4_X = 700
tree4_Y = 50

#game functions
def car1(x, y):
    screen.blit(car, (x, y))

def car_2(x, y):
    global car2_Y
    global car2_X
    screen.blit(car2, (x, y))
    car2_Y += car2Y_speed
    if car2_Y > screen_length:
        car2_X = random.randint(200, 545)
        car2_Y = random.randint(-50, 0)   


def tree1(x, y):
    global tree1_Y
    screen.blit(tree1Img, (x, y))
    tree1_Y += 10
    if tree1_Y >= screen_width:
        tree1_Y = -50


def tree2(x, y):
    global tree2_Y
    screen.blit(tree2Img, (x, y))
    tree2_Y += 10
    if tree2_Y >= screen_width:
        tree2_Y = -50


def tree3(x, y):
    global tree3_Y
    screen.blit(tree2Img, (x, y))
    tree3_Y += 10
    if tree3_Y >= screen_width:
        tree3_Y = -50


def tree4(x, y):
    global tree4_Y
    screen.blit(tree4Img, (x, y))
    tree4_Y += 10
    if tree4_Y >= screen_width:
        tree4_Y = -50

# 1st Road marker's movement
rectangleX = 426
rectangleY = 100
def roadmarker_move():
    global rectangleY
    if running == True:
        rectangleY += 10
    if rectangleY == 610:
        rectangleY = -50


#2nd road marker's movement
rectangle2_X = 426
rectangle2_Y = 410
def roadmarker2_move():
    global rectangle2_Y
    if running == True:
        rectangle2_Y += 10
    if rectangle2_Y == 610:
        rectangle2_Y = -50

#Main game loop
running = True
while running:
    screen.fill((119, 118, 110))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                carX_change = 48
            if event.key == pygame.K_LEFT:
                carX_change = -48

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                carX_change = 0
        carX += carX_change



    #drawing Road lines
    pygame.draw.line(screen, black, (639, 0), (639, 600), 10)
    pygame.draw.line(screen, black, (200, 0), (200, 600), 10)

    
    #drawing the 1st road markers
    rectangle = pygame.draw.rect(screen, black, (rectangleX, rectangleY, 15, 80))
    roadmarker_move()

    #drawing the 2nd road markers
    rectangle = pygame.draw.rect(screen, black, (rectangle2_X, rectangle2_Y, 15, 80))
    roadmarker2_move()

    #setting boundries
    if carX <= 170:
        carX = 170
    elif carX >= 547:
        carX = 547

    car1(carX, carY)
    car_2(car2_X, car2_Y)

    #collision detecting
    car_rect = car.get_rect()
    car_rect.topleft = (carX, carY)
    
    car2_rect = car2.get_rect()
    car2_rect.topleft = (car2_X, car2_Y)
    
    if ( car_rect.colliderect(car2_rect) ):
        print( "car hit tree" )

    tree1(tree1_X, tree1_Y)
    tree2(tree2_X, tree2_Y)
    tree3(tree3_X, tree3_Y)
    tree4(tree4_X, tree4_Y)
    clock.tick(FPS)
    pygame.display.update()

pygame.quit()

Upvotes: 3

Related Questions