pygame事件循环出问题

0 投票
1 回答
1388 浏览
提问于 2025-04-18 07:15

我是Pygame的新手,正在尝试制作一个类似于《Flappy Bird》的游戏。我想设置控制方式,让玩家按住跳跃键时,鸟不会一直跳。玩家需要不断点击跳跃键才能让鸟保持在空中,就像原版游戏那样。我试过使用pygame.key.set_repeat()来关闭按键重复功能,但似乎没有效果。从查看其他关于这个话题的帖子,我开始觉得可能是我的事件循环出了问题。

谢谢你的帮助!

我的代码:

import pygame

class Bird(pygame.sprite.Sprite):
    def __init__(self):
        #load pic of bird
        self.image = pygame.image.load('ball.png')
        #sets bird pic as a rectangle object and moves position to centre
        self.rect = pygame.rect.Rect((320, 240), self.image.get_size())

        #default value for gravity
        self.dy = 0 #how much to add to current player position

    def update(self, dt, game):
        pygame.key.set_repeat()
        key = pygame.key.get_pressed()
        if key[pygame.K_UP]:
            print "jump!!!"
            self.dy = -400

        #apply gravity
        self.dy = min(400, self.dy + 40)
        self.rect.y += self.dy * dt

        #collision detection
        if(self.rect.top <= 0):   #top
            self.rect.y = 0
            self.dy = -4
        elif(self.rect.bottom >= 480):   #ground
            self.rect.y = (480-self.rect.width)

        #blit image to screen
        screen.blit(self.image, (320, self.rect.y))
        pygame.display.flip()

        print self.rect.center
        print self.dy

class Ground(pygame.sprite.Sprite):
    def __init__(self):
        self.image = pygame.image.load('ground.png')
        self.rect = pygame.rect.Rect((0, 480-self.image.get_width()), self.image.get_size())



class Game(object):
    def main(self, screen):
        clock = pygame.time.Clock()

        #create background and player object
        background = pygame.image.load('background.png')
        #instantiate bird object
        self.bird = Bird()
        self.ground = Ground()

        while 1:

            dt = clock.tick(30)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return
                if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                    return

            screen.blit(background, (0, 0))
            pygame.display.flip()
            self.bird.update(dt / 1000., self)  #for some reason, update must go last


if __name__ == '__main__':
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    Game().main(screen)
    pygame.quit()

1 个回答

2

pygame.key.set_repeat() 在这里没有任何作用,因为默认情况下按键重复是关闭的。

你的错误其实很简单:你的程序在 "update()" 方法里检查 K_UP 键是否 当前 被按下,但你应该只检查事件,因为按键的按下是通过事件来捕捉的。

简单来说:事件告诉你某个键是否被按下,而 "get_pressed()" 则告诉你某个键是否 此刻 被按下。

所以你需要写一个像 "jump()" 这样的函数,并在接收到 K_UP 被按下的事件时执行它,而不是在 "update()" 方法里检查按键状态。别忘了把跳跃的代码从 "update()" 方法里删掉哦!

class Bird(pygame.sprite.Sprite):

    def jump(self):
        print "jump!!!"
        self.dy = -400

(...)

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        return
    if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
        return
    if event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
        self.bird.jump()

撰写回答