0

I'm making a Python game with Pygame and I am currently working on the hitbox. The program should pause (set play=False) whenever the player collides with an enemy.

It only "works" when I comment out all the enemy movement (line 56-64), but that is clearly not the best option. I have read about Pygame having it's own hitbox collision system but couldn't figure it out.

The game's code:

import pygame
import threading
from random import randint
from time import sleep

pygame.init()
window = pygame.display.set_mode((900, 900))
bg = pygame.image.load("BACKGROUND IMAGE HERE").convert()

class Entity:
    def __init__(self):
        self.W = 50
        self.H = 50
        self.X = 420
        self.Y = 400
        self.speed = 1/10
        self.hitbox = (self.X,self.Y,50,50) #Try out stuff

    def takeDamage(self):
        print("YOU'VE BEEN HIT!")

class Enemy(Entity): # inherit Entity
    def __init__(self):
        Entity.__init__(self) # get all traits of an entity

class Player(Entity): # inherit Entity
    def __init__(self):
        Entity.__init__(self) # get all traits of an entity
        self.X = 300 # overwrite specific traits
        self.Y = 300
        self.speed=1

Play=True
def Gameplay():
    global enemy_list, Entity,Play
    while True:
        window.blit(bg, [0, 0])
        keys = pygame.key.get_pressed()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        if Play:
            if keys[pygame.K_w] and player.Y >= 1:
                    player.Y-=player.speed
            if keys[pygame.K_s] and player.Y <= 900-player.H:
                    player.Y+=player.speed
            if keys[pygame.K_a] and player.X >= 1:
                    player.X-=player.speed
            if keys[pygame.K_d] and player.X <= 900-player.W:
                    player.X+=player.speed

        pygame.draw.rect(window, (93,124,249), (player.X, player.Y, player.W, player.H))
        if Play:
            for enemy in enemy_list:
                if enemy.X > player.X: 
                    enemy.X = enemy.X - enemy.speed
                else:
                    enemy.X = enemy.X + enemy.speed
                if enemy.Y > player.Y:
                    enemy.Y = enemy.Y - enemy.speed
                else:
                    enemy.Y = enemy.Y + enemy.speed

                pygame.draw.rect(window, (255, 50, 49), (enemy.X, enemy.Y, enemy.W, enemy.H))

                if enemy.Y <= player.Y and enemy.Y+enemy.W >= player.Y+player.W:
#PROBLEM HERE
                    Play=False

        pygame.display.update()

def EnemySpawn():
    global enemy_list,Play
    score= 0
    while True: # make enemies until Play == False
        if Play:
            score+=1
            print("Spawned an enemy! Score:", score-1)
            enemy_list.append(Enemy()) # make an instance of our class
            sleep(randint(1000, 5000)) #I know this is 1-5k Seconds

if __name__ == "__main__":
    player = Player() # notice the difference in capitalization!
    enemy_list = [] # to maintain records of all enemies made
    game_thread = threading.Thread(target=Gameplay)
    game_thread.start()
    enemy_spawner_thread = threading.Thread(target=EnemySpawn)
    enemy_spawner_thread.start()

Do you know the fix for this? Is there any better option than doing it how I have it right now?

Thomas3k24
  • 55
  • 5
  • You should really try reading the documentation on [pygame.rect](https://www.pygame.org/docs/ref/rect.html) and especially [colliderect](https://www.pygame.org/docs/ref/rect.html#pygame.Rect.colliderect) if you want to figure out collision. – Mercury Platinum May 24 '19 at 12:39

1 Answers1

2

I recommend to use a pygame.Rect object and either .collidepoint() or colliderect() to find a collision between enemy and player.

e.g. check if enemy collides with the center of the player:

player_rect = pygame.Rect(player.X, player.Y, player.W, player.H)
enemy_rect  = pygame.Rect(enemy.X, enemy.Y, enemy.W, enemy.H)
if enemy_rect.collidepoint(player_rect.center):
    Play=False

Note, instead of the .X, .Y, .W and .H properties of player and enemy you should use a pygame.Rect object.

If you want to verify, if the enemy is exactly on the player, the it is sufficient to compare the center points of the rectangles:

if enemy_rect.center == player_rect.center:
    Play=False
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Is it also possible to check if 2 rectangles collide at their edges? – Thomas3k24 May 24 '19 at 13:05
  • @Varvalian This is only possible if the rectangles have equal size, then you can do something like `enemy_rect.bottomleft == player_rect.bottomleft and enemy_rect.topright == player_rect.tpopright` but this is the same as `enemy_rect.center == player_rect.center`. If you want to chech if on rectangle is inside the other then you can use [`enemy_rect(player_rect)`](https://www.pygame.org/docs/ref/rect.html#pygame.Rect.contains`). – Rabbid76 May 24 '19 at 13:17