如何解决:pygame中的“ UnboundLocalError:分配前引用了本地变量'events'”?

时间:2019-08-04 21:55:24

标签: python python-3.x pygame pycharm

我正在按我的学分屏幕上的一个按钮,以便在按下时返回到开始屏幕。我有一个带有“事件”作为参数的按钮功能,但是当我在信用场景中使用它时。但是,会发生此错误:“ UnboundLocalError:分配前引用了本地变量'事件'”。我不明白,“事件”甚至都不是变量。有人知道如何解决这个问题吗?

  File "/Users/qingduliu/PycharmProjects/Pygame3/Shoot 'em Up.py", line 355, in credits
button(events, 10, 10, 120, 60, WHITE, GRAY, 'back')
UnboundLocalError: local variable 'events' referenced before assignment

代码

def button(events, x, y, width, height, ic, ac, action=None):

    mouse = pygame.mouse.get_pos()
    # print(mouse)

    if x + width > mouse[0] > x and y + height > mouse[1] > y:
        pygame.draw.rect(screen, ac, (x, y, width, height), 0)
        if events.type == pygame.MOUSEBUTTONDOWN and action is not None:
            if action == 'play':
                game_loop()
            elif action == 'credits':
                credits()
            elif action == 'instructions':
                instructions()
            elif action == 'back':
                start_screen()
            elif action == 'quit':
                pygame.quit()
                quit()
    else:
        pygame.draw.rect(screen, ic, (x, y, width, height), 0)


def start_screen():

    start = True

    while start:

        clock.tick(FPS)
        for events in pygame.event.get():
            if events.type == pygame.QUIT:
                pygame.quit()
                quit()

        screen.blit(background, background_rect)
        pygame.transform.scale(player_img, (50, 38))
        player_img.set_colorkey(BLACK)
        screen.blit(player_img, (10, HEIGHT - 120))
        screen.blit(player_img, (WIDTH - 110, HEIGHT - 120))
        bullet_img.set_colorkey(BLACK)
        screen.blit(bullet_img, (55, 400))
        screen.blit(bullet_img, (415, 400))
        screen_meteor.set_colorkey(BLACK)
        screen.blit(screen_meteor, (5, 220))
        screen.blit(screen_meteor, (WIDTH - 105, 220))
        boss_img.set_colorkey(BLACK)
        pygame.transform.scale(boss_img, (50, 38))
        screen.blit(boss_img, (190, 25))

        button(events, 180, 285, 120, 60, BLUE, LIGHT_BLUE, 'play')
        button(events, 202, HEIGHT - 150, 80, 40, WHITE, GRAY, 'quit')
        button(events, 310, 45, 140, 30, WHITE, GRAY, 'credits')
        button(events, 20, 45, 140, 30, WHITE, GRAY, 'instructions')

        draw_text(screen, "Shoot 'Em Up", 80, WIDTH / 2, HEIGHT / 4, WHITE)
        draw_text(screen, "Instructions", 30, 90, 53, BLACK)
        draw_text(screen, "Credits", 35, 378, 50, BLACK)
        draw_text(screen, "Play", 55, WIDTH / 2, HEIGHT / 2, WHITE)
        draw_text(screen, "Quit", 30, WIDTH / 2, HEIGHT - 137, BLUE)

        pygame.display.flip()


def credits():

    credits = True

    while credits:

        clock.tick(FPS)
        for events in pygame.event.get():
            if events.type == pygame.QUIT:
                pygame.quit()
                quit()

        screen.blit(background, background_rect)
        draw_text(screen, "Credits", 100, WIDTH / 2, 15, WHITE)
        draw_text(screen, "Game Template:", 60, WIDTH / 2, 95, WHITE)
        draw_text(screen, "Kids Can Code, Shmup, Chris Bradfield", 35, WIDTH / 2, 155, WHITE)
        draw_text(screen, "Youtube Channel", 30, WIDTH / 2, 195, WHITE)
        draw_text(screen, "https://www.youtube.com/channel/UCNaPQ5uLX5iIEHUCLmfAgKg", 20, WIDTH / 2, 220, WHITE)
        draw_text(screen, "Blog", 30, WIDTH / 2, 245, WHITE)
        draw_text(screen, "http://kidscancode.org/blog/tags/pygame/", 20, WIDTH / 2, 270, WHITE)
        draw_text(screen, "Music:", 60, WIDTH / 2, 300, WHITE)
        draw_text(screen, "Frozen Jam by tgfcoder", 45, WIDTH / 2, 345, WHITE)
        draw_text(screen, "Twitter", 30, WIDTH / 2, 380, WHITE)
        draw_text(screen, "<https://twitter.com/tgfcoder>", 20, WIDTH / 2, 403, WHITE)
        draw_text(screen, "licensed under CC-BY-3 <http://creativecommons.org/licenses/by/3.0/>", 15, WIDTH / 2, 425, WHITE)
        draw_text(screen, "Art:", 60, WIDTH / 2, 450, WHITE)
        draw_text(screen, "Kenney.nl", 35, WIDTH / 2, 490, WHITE)
        draw_text(screen, "https://opengameart.org/", 20, WIDTH / 2, 520, WHITE)
        draw_text(screen, "Background https://imgur.com/bHiPMju by Chris Bradfield", 20, WIDTH / 2, 540, WHITE)
        draw_text(screen, "Thank You for all your help and hard work!", 32, WIDTH / 2, 560, RED)

        button(events, 10, 10, 120, 60, WHITE, GRAY, 'back')
        draw_text(screen, "Back", 25, 13, 13, WHITE)

        pygame.display.flip()

2 个答案:

答案 0 :(得分:0)

 button(events, 180, 285, 120, 60, BLUE, LIGHT_BLUE, 'play')

在第一个代码块中,您引用了for循环之外的事件,该循环定义了events变量

答案 1 :(得分:0)

您必须将按钮移至事件循环,因为按钮必须检查每个事件。

因为使用了用鼠标检查冲突并在一个代码中绘制按钮的功能,所以必须将事件循环移到按钮上。

    clock.tick(FPS)

    # - draw background, etc. -

    screen.blit(background, background_rect)
    pygame.transform.scale(player_img, (50, 38))
    player_img.set_colorkey(BLACK)
    screen.blit(player_img, (10, HEIGHT - 120))
    screen.blit(player_img, (WIDTH - 110, HEIGHT - 120))
    bullet_img.set_colorkey(BLACK)
    screen.blit(bullet_img, (55, 400))
    screen.blit(bullet_img, (415, 400))
    screen_meteor.set_colorkey(BLACK)
    screen.blit(screen_meteor, (5, 220))
    screen.blit(screen_meteor, (WIDTH - 105, 220))
    boss_img.set_colorkey(BLACK)
    pygame.transform.scale(boss_img, (50, 38))
    screen.blit(boss_img, (190, 25))

    # - buttons - events + draw  -

    for events in pygame.event.get():
        if events.type == pygame.QUIT:
            pygame.quit()
            quit()

        button(events, 180, 285, 120, 60, BLUE, LIGHT_BLUE, 'play')
        button(events, 202, HEIGHT - 150, 80, 40, WHITE, GRAY, 'quit')
        button(events, 310, 45, 140, 30, WHITE, GRAY, 'credits')
        button(events, 20, 45, 140, 30, WHITE, GRAY, 'instructions')

    # - draw text on buttons -

    draw_text(screen, "Shoot 'Em Up", 80, WIDTH / 2, HEIGHT / 4, WHITE)
    draw_text(screen, "Instructions", 30, 90, 53, BLACK)
    draw_text(screen, "Credits", 35, 378, 50, BLACK)
    draw_text(screen, "Play", 55, WIDTH / 2, HEIGHT / 2, WHITE)
    draw_text(screen, "Quit", 30, WIDTH / 2, HEIGHT - 137, BLUE)

    # - send all on screen -

    pygame.display.flip()

代码很奇怪,因为现在它为每个事件多次绘制按钮。但是要更改它,您将必须将按钮拆分为两个功能,或者创建具有两个功能的类Button-draw()handle_event()


编辑:您可以尝试使用click = pygame.mouse.get_pressed()lick[0] == 1代替events,这样就不必进入for events循环了,但是当您删除按钮并将新按钮放在同一位置时,可能会出现问题。 Python会如此快地执行操作,以至于您仍然会按住按钮,而python会认为您已按下了新按钮。

def button(x, y, width, height, ic, ac, action=None):

    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    # print(mouse)

    if x + width > mouse[0] > x and y + height > mouse[1] > y:
        pygame.draw.rect(screen, ac, (x, y, width, height), 0)
        if click[0] == 1 and action is not None:
            if action == 'play':
                game_loop()
            elif action == 'credits':
                credits()
            elif action == 'instructions':
                instructions()
            elif action == 'back':
                start_screen()
            elif action == 'quit':
                pygame.quit()
                quit()
    else:
        pygame.draw.rect(screen, ic, (x, y, width, height), 0)

您可以分配给action函数名称,而不是文本'“ credits” ,“指令” ect. and then you can run it as action()`

def button(x, y, width, height, ic, ac, action=None):

    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    # print(mouse)

    if x + width > mouse[0] > x and y + height > mouse[1] > y:
        pygame.draw.rect(screen, ac, (x, y, width, height), 0)
        if click[0] == 1 and action is not None:
            action()
    else:
        pygame.draw.rect(screen, ic, (x, y, width, height), 0)


button(180, 285, 120, 60, BLUE, LIGHT_BLUE, game_loop)
button(310, 45, 140, 30, WHITE, GRAY, credits)
button(20, 45, 140, 30, WHITE, GRAY, instructions)

button(202, HEIGHT - 150, 80, 40, WHITE, GRAY, game_quit)

def game_quit():
    pygame.quit()
    quit()

button(..., start_screen)