Pygame movement error and pygame collision error

Question:

I am trying to make a game with pygame where you can doge an asteroid having 2 issues that I need help with:

  1. How to make two images collide so I can end the game. I am having trouble because the two images are not rectangles so I can’t use rect collide command.

  2. Every time I move the character the velocity of the asteroid gets slower.

here is my code:

# Setup
import pygame
pygame.init()
HEIGHT = 500
WIDTH = 500
display = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Speed Of Light")
run = True

# BG
background_image = pygame.image.load("background.png").convert_alpha()
# Player
player = pygame.image.load("player.png").convert_alpha()
class Player():
    def __init__(self, x, y, image, scale, vel):
        width = image.get_width()
        height = image.get_height()
        self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale)))
        self.rect = self.image
        self.rect_x = x
        self.rect_y = y
        self.vel = vel
    def draw(self):
        display.blit(self.rect, (self.rect_x,self.rect_y))

    def move(self, direction):
        display.blit(self.rect, (self.rect_x, self.rect_y))
        pygame.display.update()
        if direction == "right" and self.rect_x <= 450:
            self.rect_x = self.rect_x + self.vel
            display.blit(self.rect, (self.rect_x, self.rect_y))
            pygame.display.update()
        if direction == "left" and self.rect_x >= 0:
            self.rect_x = self.rect_x - self.vel
            display.blit(self.rect, (self.rect_x, self.rect_y))
            pygame.display.update()

    def current_x(self):
        return self.rect_x

char_x = 250
char_y = 385
character = Player(image = player, scale = 0.2, x = char_x, y = char_y, vel=0.3)

# Asteroid
ball = pygame.image.load(r"asteroid.png").convert_alpha()
class Asteroid:
    def __init__(self, image, vel, scale, x):
        width = image.get_width()
        height = image.get_height()
        self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale)))
        self.vel = vel
        self.y = 0
        self.x = x
    def move_asteroid(self, x):
        if self.y > 500:
            self.y = 0
            self.x = x
        display.blit(self.image, (self.x, self.y))
        self.y = self.y + self.vel

asteroid = Asteroid(ball, 0.2, 0.2, 250)

# Check Collision
def check_collision(player, asteroid):
    player = player.rect.get_rect()
    asteroid = asteroid.rect.get_rect()
    if player.collidepoint(asteroid) == True:
        return True
    return False

# Main
while run:
    # Close
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    # Activate BG
    display.blit(background_image, (0, 0))

    # Move Astroid
    asteroid_main = asteroid.move_asteroid(character.current_x()-65)

    # Draw Player
    character.draw()

    # Move Player
    keys = pygame.key.get_pressed()
    if keys[pygame.K_RIGHT]:
        character.move("right")
    if keys[pygame.K_LEFT]:
        character.move("left")
    # Check collision
    # run = False
    # Updates screen
    pygame.display.update()
Asked By: Ultra Legend

||

Answers:

The modified part of your code solves the issue Every time I move the character the velocity of the asteroid gets slower:

# Move Player
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
    character.move("right")
    character.move("right")
elif keys[pygame.K_LEFT]:
    character.move("left")
    character.move("left")
else: 
    character.move("right")
    character.move("left")

Feel free to improve your code so that every loop run requires same amount of time. The solution above is only a demonstration of the principle making every loop run requiring same amount of CPU-time. There are better ways of achieving the same effect.

In order to suggest a proper solution for checking collision you need to provide the images and explain your idea when a collision between them should occur.

Below your entire code not slowing down by player movement and with very simple rudimentary implemented collision detection shutting down the game on collision:

import pygame
pygame.init()
HEIGHT = 500
WIDTH = 500
display = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Speed Of Light")
run = True

# BG
background_image = pygame.image.load("background.png").convert_alpha()
# Player
player = pygame.image.load("player.png").convert_alpha()

class Player():
    def __init__(self, x, y, image, scale, vel):
        width = image.get_width()
        height = image.get_height()
        self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale)))
        self.rect = self.image
        self.rect_x = x
        self.rect_y = y
        self.vel = vel
    def draw(self):
        display.blit(self.rect, (self.rect_x,self.rect_y))

    def move(self, direction):
        display.blit(self.rect, (self.rect_x, self.rect_y))
        pygame.display.update()
        if direction == "right" and self.rect_x <= 450:
            self.rect_x = self.rect_x + self.vel
            display.blit(self.rect, (self.rect_x, self.rect_y))
            pygame.display.update()
        if direction == "left" and self.rect_x >= 0:
            self.rect_x = self.rect_x - self.vel
            display.blit(self.rect, (self.rect_x, self.rect_y))
            pygame.display.update()

    def current_x(self):
        return self.rect_x

char_x = 250
char_y = 385
character = Player(image = player, scale = 0.2, x = char_x, y = char_y, vel=0.3)

# Asteroid
ball = pygame.image.load("asteroid.png").convert_alpha()
class Asteroid:
    def __init__(self, image, vel, scale, x):
        width = image.get_width()
        height = image.get_height()
        self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale)))
        self.rect  = self.image
        self.vel = vel
        self.y = 0
        self.x = x
    def move_asteroid(self, x):
        if self.y > 500:
            self.y = 0
            self.x = x
        display.blit(self.image, (self.x, self.y))
        self.y = self.y + self.vel

asteroid = Asteroid(ball, 0.2, 0.2, 250)

# Check Collision
def check_collision(character, asteroid):
    print(int(asteroid.y), int(character.rect_x), int(asteroid.x))
    if asteroid.y > 285 and ( abs(character.rect_x - asteroid.x) < 135 ):
        return True
    return False

# Main
while run:
    # Close
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    # Activate BG
    display.blit(background_image, (0, 0))

    # Move Astroid
    asteroid.move_asteroid(character.current_x()-65)

    # Draw Player
    character.draw()

    # Move Player
    keys = pygame.key.get_pressed()
    if keys[pygame.K_RIGHT]:
        character.move("right")
        character.move("right")
    elif keys[pygame.K_LEFT]:
        character.move("left")
        character.move("left")
    else: 
        character.move("right")
        character.move("left")
    
    # Check collision
    if check_collision(character, asteroid): 
       run = False
        
    # run = False
    # Updates screen
    pygame.display.update()
Answered By: Claudio
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.