RaptoRR
RaptoRR

Reputation: 55

I cant find how to build a good pygame collision system

so i have a problem with my collisions. My code is kinda funky because its for a gamejam in a time of 2 days and i havent got to sorting it yet. so i want the code to print something if the honey touches the player. i can work my way up from there. here is the code i will attach the imagesenter image description hereenter image description hereenter image description hereenter image description here

import pygame
from pygame.locals import *
from random import randint

pygame.init()
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")

#game variables 
screen_width = 720
screen_height = 484
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60

honeySpeed = 6

class Bee(pygame.sprite.Sprite):
    def __init__(self, x, y, alive, speed, score):
        pygame.sprite.Sprite.__init__(self)
        self.alive = alive
        self.speed = speed
        self.score = score
        self.img = beeImg
        self.rect = self.img.get_rect()
        self.rect.center = [x, y]
        self.x = x
        self.y = y
    def draw(self):
        #DRAWING
        screen.blit(self.img, (self.x, self.y))
        # MOVEMENT
        key_input = pygame.key.get_pressed()
        if key_input[pygame.K_LEFT]:
            player.x -= player.speed
        elif key_input[pygame.K_RIGHT]:
            player.x += player.speed

class Honey(pygame.sprite.Sprite):
    def __init__(self, x, y,speed):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.speed = speed
    
        
        self.image = honeyImg
        
        self.image = pygame.transform.scale(honeyImg, (60,60))
        
        
        self.rect = self.image.get_rect()
        self.rect.center = [x,y]
        
    def update(self):
        screen.blit(self.image, (self.x,self.y))
        self.y += 5
        
        if self.y > screen_height:
            self.kill()


player = Bee(screen_width/2-50, screen_height/2 +120, True, 8, 0)

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')

honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)

running = True
run = True
while run:
    clock.tick(fps)
    time_now = pygame.time.get_ticks()
    if time_now - last_hun > hun_frequency:
        newHoney = Honey(randint(0, screen_width), -50, honeySpeed)
        honeyGroup.add(newHoney)
        last_hun = time_now  

    #draw pics
    screen.blit(bgImg,(0,0))
    
    hits = pygame.sprite.spritecollide(player, honeyGroup, False)
    if hits:
        print("touched")
    player.draw()
    #newHoney.draw()
    honeyGroup.draw(screen)
    
    
    honeyGroup.update()

    hits = pygame.sprite.spritecollide(player, honeyGroup, False)
    if hits:
        print("touched")

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

    pygame.display.update()
    
pygame.quit()

Upvotes: 1

Views: 59

Answers (1)

Rabbid76
Rabbid76

Reputation: 211077

I recommend to use Pygame mask collision (see also Can't figure out how to check mask collision between two sprites). All you need to do is to use pygame.sprite.collide_mask():

Tests for collision between two sprites, by testing if their bitmasks overlap (uses pygame.mask.Mask.overlap()). If the sprites have a mask attribute, it is used as the mask, otherwise a mask is created from the sprite's image.

Change in your code:

hits = pygame.sprite.spritecollide(player, honeyGroup, False)

hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)

However, see How do I detect collision in pygame? and Making and using pygame sprites. The 'rect' and image (not img) attribute is used for collision detection. You need to update the position of the rectangle. You do not need the x and y attribute at all. Use rect.x and rect.y:

class Bee(pygame.sprite.Sprite):
    def __init__(self, x, y, alive, speed, score):
        pygame.sprite.Sprite.__init__(self)
        self.alive = alive
        self.speed = speed
        self.score = score
        self.image = beeImg
        self.rect = self.image.get_rect(center = (x, y))

    def draw(self):
        screen.blit(self.image, self.rect)
        key_input = pygame.key.get_pressed()
        if key_input[pygame.K_LEFT]:
            self.rect.x -= self.speed
        elif key_input[pygame.K_RIGHT]:
            self.rect.x += self.speed
class Honey(pygame.sprite.Sprite):
    def __init__(self, x, y,speed):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = honeyImg
        self.image = pygame.transform.scale(honeyImg, (60,60))
        self.rect = self.image.get_rect(center = (x, y))
        
    def update(self):
        screen.blit(self.image, self.rect)
        self.rect.y += 5
        if self.rect.y > screen_height:
            self.kill()

Complete example:

enter image description here

import pygame
from pygame.locals import *
from random import randint

class Bee(pygame.sprite.Sprite):
    def __init__(self, x, y, alive, speed, score):
        pygame.sprite.Sprite.__init__(self)
        self.alive = alive
        self.speed = speed
        self.score = score
        self.image = beeImg
        self.rect = self.image.get_rect(center = (x, y))

    def update(self):
        key_input = pygame.key.get_pressed()
        if key_input[pygame.K_LEFT]:
            self.rect.x -= self.speed
        elif key_input[pygame.K_RIGHT]:
            self.rect.x += self.speed

class Honey(pygame.sprite.Sprite):
    def __init__(self, x, y,speed):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = honeyImg
        self.image = pygame.transform.scale(honeyImg, (60,60))
        self.rect = self.image.get_rect(center = (x, y))
        
    def update(self):
        self.rect.y += 5
        if self.rect.y > screen_height:
            self.kill()

pygame.init()

#game variables 
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60
honeySpeed = 6
screen_width = 720
screen_height = 484

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")

player = Bee(screen_width/2-50, screen_height/2 +120, True, 8, 0)
honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)

run = True
while run:
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    time_now = pygame.time.get_ticks()
    if time_now - last_hun > hun_frequency:
        newHoney = Honey(randint(0, screen_width), -50, honeySpeed)
        honeyGroup.add(newHoney)
        last_hun = time_now  

    #draw pics
    honeyGroup.update()
    player.update()
    
    hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)
    if hits:
        print(f"touched")
        hits[0].kill()
   
    screen.blit(bgImg,(0,0))
    honeyGroup.draw(screen)
    playerGroup.draw(screen)
    pygame.display.update()
    
pygame.quit()

Upvotes: 1

Related Questions