我找不到如何构建良好的 pygame 碰撞系统

I cant find how to build a good pygame collision system

所以我的碰撞有问题。我的代码有点古怪,因为它用于 2 天的 gamejam,我还没有对它进行排序。所以我希望代码在蜂蜜接触播放器时打印一些东西。我可以从那里开始工作。这是代码 我会附上图片enter 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()

我推荐使用 (see also ). 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.

代码更改:

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

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

但是,参见 How do I detect collision in pygame? and Making and using pygame sprites'rect'image(不是 img)属性用于碰撞检测。您需要更新矩形的位置。您根本不需要 xy 属性。使用 rect.xrect.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()

完整示例:

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()