Search code examples
pythonpython-3.xpygame

Game stops despite no collision


import sys
import random
import pygame

pygame.init()

WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))

pygame.display.set_caption('My Game')

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 255)

player1 = Player(350, 450, 50, 50, 15, BLUE, screen)
enemy1 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy2 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy3 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy4 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy5 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy7 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy8 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy6 = Enemy(random.randint(0, 750), 0, 50, 50, 6, RED, screen)
enemy_list = [enemy1, enemy2, enemy3, enemy4, enemy5, enemy6, enemy7, enemy8]

class Player(): #for making player  object
    def __init__(self, x, y, width, height, vel, color, screen):
        self.x = x
        self.y = y
        self.vel = vel
        self.color = color
        self.screen = screen
        self.width = width
        self.height = height

    def move(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] and self.x > 0:
            self.x -= self.vel
        if keys[pygame.K_RIGHT] and self.x < 750:
            self.x += self.vel
        if keys[pygame.K_UP] and self.y > 0:
            self.y -= self.vel 
        if keys[pygame.K_DOWN] and self.y < 550:
            self.y += self.vel
        self.rect = (self.x, self.y, self.width, self.height)

    def drawPlayer(self):
        pygame.draw.rect(self.screen, self.color, (self.x, self.y, self.width, self.height))

class Enemy():# making enemy object
    randlist =[]
    x_pos = random.randint(50, 70)
    y_pos = 0
    def __init__(self, ex, ey, ewidth, eheight, evel, ecolor, screen):
        self.ex = ex
        self.ey = ey
        self.evel = evel
        self.ecolor = ecolor
        self.screen = screen
        self.ewidth = ewidth
        self.eheight = eheight

    def enemy_move(self):
        #probaly change this to vary speed in objects 
        self.ey += self.evel
        if self.ey > 775:
            self.ex = random.randint(0, 750)
            self.ey = random.randint(0, 100)

    def drawEnemy(self):
        #change this to get more enemies
        pygame.draw.rect(self.screen, self.ecolor, (self.ex, self.ey, self.ewidth, self.eheight))

def collisions(list):#the issue at hand. I dont know whats wrong with it.
    if any((enemy.ex >= player1.x and enemy.ex < (player1.x + player1.width)) for enemy in enemy_list) or any((player1.x >= enemy.ex and player1.x < (enemy.ex + enemy.ewidth)) for enemy in enemy_list):
        if any((enemy.ey >= player1.y and enemy.ey < (player1.y + player1.height)) for enemy in enemy_list) or any((player1.y >= enemy.ey and player1.y < (enemy.ey + enemy.eheight)) for enemy in enemy_list):
            return True
    return False

def main():
    is_running = True
    while is_running:
        FPS = pygame.time.Clock()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        screen.fill(BLACK)
        player1.drawPlayer()
        for enemy in enemy_list:
            enemy.drawEnemy()
        if collisions(enemy_list):
            is_running = False
        player1.move()
        for enemy in enemy_list:
            enemy.enemy_move()
        pygame.display.update()
        FPS.tick(60)

main()

There seems to be a problem with my collision function, but I can't seem to find the issue. I have no clue what's causing my game to randomly stop. I tried replacing the return values with print statements to see whats wrong with my collisions function, and it turns out that my object randomly collides with the enemy objects even though the blocks themselves don touch.


Solution

  • I recommend to us pygame.Rect.colliderect for the collision test of 2 rectangular objects:

    def collisions(list):
        player_rect = pygame.Rect(player1.x, player1.y, player1.width, player1.height)
        return any(
            player_rect.colliderect((enemy.ex, enemy.ey, enemy.ewidth, enemy.eheight))
            for enemy in enemy_list)
    

    A further improvement would be to store the hit boxes in an attribute (.rect) of the Player and Enemy objects. In that case it would be possible to do something like:

    def collisions(list):
        return any(player.rect.colliderect(enemy.rect) for enemy in enemy_list)