简体   繁体   中英

Trouble with pygame event loop

Pygame newbie here, I'm trying to make a Flappy Bird clone. I'd like to set the controls so that holding down the jump key will not keep the bird jumping. The player would have to keep tapping jump to keep the bird afloat, like the original game. I tried using pygame.key.set_repeat() to turn off key repeat, but it doesn't seem to be working. From reviewing other posts on this same topic, I'm starting to think it might be a problem in my event loop.

Thanks for you help!

My code:

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

pygame.key.set_repeat() doesn't change anything here, because the key repeat is disabled by default.

And your error is rather simple: your program checks in "update()" method if K_UP is currently pressed - but you should check only events, because pushing button is intercepted by events.

In short: event tells you if key was pressed and "get_pressed()" tells if key is pressed right now .

So you have to write method like "jump()" and execute it when you receive event with K_UP pressed - not checking key state inside "update()" method. And don't forget about deleting jump code from "update()" method!

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM