3

I'm quite new to pygame and came across a bug that i just can't fix on my own. I'm trying to program a Flappy Bird game. The Problem is that the collision detection works, but it also messes with my sprites. If i manage to get past the first obstacle while playing, then the gap resets itself randomly. But the gap should always be the same, just on another position. If i remove the collision detection, it works perfectly fine. Any ideas?

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)
The line im talking about:
        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()
4

1 回答 1

5

这与碰撞检测无关,它与精灵组中精灵的顺序有关,因为精灵组在内部使用无序的字典(在 Python 版本 < 3.6 中)。所以如果Pipe1精灵在组中先来,游戏会正常运行,但是如果Pipe2精灵先来,那么它的update方法也会先被调用,并randomyupdate使用Pipe1的previous来设置精灵的新中心坐标。

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

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变量并始终randomyupdate使用Pipe1.

于 2018-02-25T21:21:24.353 回答