Pygame 碰撞错误

Pygame Collision Bug

我是 pygame 的新手,遇到了一个我无法自行修复的错误。我正在尝试编写一个 Flappy Bird 游戏。问题是碰撞检测有效,但它也弄乱了我的精灵。如果我在玩游戏时设法越过第一个障碍,那么间隙会随机重置。但差距应该总是一样的,只是在另一个位置上。如果我删除碰撞检测,它工作得很好。有什么想法吗?

import pygame    
import random      

randomy = random.randint(-150, 150)

class Bird(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.Surface((25,25))
        self.image.fill((255,255,255))
        self.rect = self.image.get_rect()
        self.rect.center = (100, 200)
        self.velocity = 0.05
        self.acceleration =0.4

    def update(self):
        self.rect.y += self.velocity
        self.velocity += self.acceleration
        if self.rect.bottom > 590:
            self.velocity = 0
            self.acceleration = 0                                


class Pipe1(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.Surface((85, 500))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect()
        self.rect.center = (500, randomy)
        self.randomyupdate = random.randint(-150, 150)

    def update(self):
        self.rect.x -= 2
        if self.rect.x < -90:
            self.randomyupdate = random.randint(-150, 150)
            self.rect.center = (450, self.randomyupdate)

class Pipe2(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.Surface((85, 500))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect()
        self.rect.center = (500, (randomy +640))

    def update(self):
        self.rect.x -= 2
        self.randomyupdate = Pipe1.randomyupdate
        if self.rect.x < -90:
            self.rect.center = (450, (self.randomyupdate + 640))


pygame.init()
pygame.mouse.set_visible(1)
pygame.key.set_repeat(1, 30)
pygame.display.set_caption('Crappy Bird')
clock = pygame.time.Clock()

Bird_sprite = pygame.sprite.Group()
Pipe_sprite = pygame.sprite.Group()
Bird = Bird()
Pipe1 = Pipe1()
Pipe2 = Pipe2 ()
Bird_sprite.add(Bird)
Pipe_sprite.add(Pipe1)
Pipe_sprite.add(Pipe2)


def main():
    running = True
    while running:
        clock.tick(60)
        screen = pygame.display.set_mode((400,600))
        screen.fill((0,0,0))
        Bird_sprite.update()
        Pipe_sprite.update()
        Bird_sprite.draw(screen)
        Pipe_sprite.draw(screen)
我正在谈论的那行:
        collide = pygame.sprite.spritecollideany(Bird, Pipe_sprite)
        if collide:
            running = False

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.event.post(pygame.event.Event(pygame.QUIT))
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    Bird.rect.y -= 85
                    Bird.velocity = 0.05
                    Bird.acceleration = 0.4
                    Bird.rect.y += Bird.velocity
                    Bird.velocity += Bird.acceleration
        pygame.display.flip()


if __name__ == '__main__':
    main()

这与碰撞检测无关,它与精灵组中精灵的顺序有关,顺序可能会有所不同,因为精灵组在内部使用无序的字典(在 Python 版本 < 3.6).因此,如果 Pipe1 精灵在组中排在第一位,游戏将正常运行,但如果 Pipe2 精灵排在第一位,则它的 update 方法也将首先调用,并且之前的 [= Pipe1的15=]用于设置精灵新的中心坐标。

要解决此问题,您可以将精灵组转换为有序组,例如

Pipe_sprite = pygame.sprite.OrderedUpdates()

或每帧更新Pipe2的矩形,

def update(self):
    self.rect.x -= 2
    self.rect.centery = Pipe1.randomyupdate + 640

    if self.rect.x < -90:
        self.rect.center = (450, Pipe1.randomyupdate + 640)

此外,删除全局 randomy 变量并始终使用 Pipe1randomyupdate 属性。