Pygame 中不同屏幕上的按钮

Buttons on different screens in Pygame

我正在制作一个带有开始和帮助菜单以及其他功能的程序。 "main menu" 上的按钮工作正常,但是一旦我进入“帮助”菜单,我为屏幕导航编程的按钮就无法正常工作。请随时查看下面的代码。我不断收到一条错误消息 "BackHelpRect not defined"。 BackHelpRect 是我在图像按钮周围绘制的一个矩形(对于我的所有其他按钮),用于检测鼠标何时触摸它们。它适用于主菜单按钮,但一旦我进入帮助菜单,这些按钮的矩形 "disappear"。如果您有解决方案,请回复,我们将不胜感激。 :)

抱歉,我已经附上了我的全部代码,但是所有的东西都是在其他函数中调用的,而且它们都是相互同步的。很长请见谅

import pygame
import time
import smtplib
import webbrowser
pygame.init() # Starts pygame.
white = (255, 255, 255)
blue = (0, 100, 175)
black = (0, 0, 0)# Initialising Python with colours and a window size.
Event = []
AllTasks = []
MenuStatus = ""
def OpenMainMenu(): # To open Main Menu.
    MenuStatus = "Main Menu" # In case the code needs to know what menu is currently projected.
    pygame.display.set_caption("Main Menu") # Naming the New Window.
    CurrentMenu = pygame.image.load(r'D:\Holiday Planner Screen Resources\Main Menu.jpg') # Opening a custom made Screen.
    Screen.blit(CurrentMenu, (0, 0))
    CreateEventB()
    OpenEventB()
    HelpB()
    pygame.display.update()# Loads the Main Menu Screen.
    ButtonInteract()
def CreateEventB(): # To Open the "Create Menu Button".
    CreateButton = pygame.image.load(r'D:\Holiday Planner Screen Resources\Create Event.jpg') # Open the custom button design.
    CreateButton = pygame.transform.scale(CreateButton, (174, 85))
    global CreateRect
    CreateRect = Screen.blit(CreateButton, (425, 325))
    pygame.display.update(CreateRect)
def OpenEventB(): # To Open the "Create Menu Button".
    OpenButton = pygame.image.load(r'D:\Holiday Planner Screen Resources\Open Event.jpg') # Open the custom button design.
    OpenButton = pygame.transform.scale(OpenButton, (179, 85))
    global OpenRect
    OpenRect = Screen.blit(OpenButton, (225, 325))
    pygame.display.update(OpenRect)
def HelpB():
    HelpButton = pygame.image.load(r'D:\Holiday Planner Screen Resources\Help Button.jpg') # Open the custom button design.
    HelpButton = pygame.transform.scale(HelpButton, (151, 51))
    global HelpRect
    HelpRect = Screen.blit(HelpButton, (335, 415))
   pygame.display.update(HelpRect)
def BackHelp():
    BackHelpB = pygame.image.load(r'D:\Holiday Planner Screen Resources\BackHelp.jpg') # Open the custom button design.
    BackHelpB = pygame.transform.scale(BackHelpB, (235, 84))
    global BackHelpRect
    BackHelpRect = Screen.blit(BackHelpB, (45, 490))
    pygame.display.update(BackHelpRect)
def NextHelp():
    NextHelpB = pygame.image.load(r'D:\Holiday Planner Screen Resources\NextHelp.jpg') # Open the custom button design.
    NextHelpB = pygame.transform.scale(NextHelpB, (233, 85))
    global NextHelpRect
    NextHelpRect = Screen.blit(NextHelpB, (545, 490))
    pygame.display.update(NextHelpRect)
def FinishHelp():
    FinishHelpB = pygame.image.load(r'D:\Holiday Planner Screen Resources\FinishHelp.jpg') # Open the custom button design.
    FinishHelpB = pygame.transform.scale(NextHelpB, (230, 85))
    global FinishHelpRect
    FinishHelpRect = Screen.blit(FinishHelpRect, (545, 490))
    pygame.display.update(FinishHelpRect)  
def ButtonInteract(): # A function that helps to connect button interactions to their respective functions.
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if CreateRect.collidepoint(event.pos):
                    CreateEvent()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if OpenRect.collidepoint(event.pos):
                    Event, AllTasks = OpenEvent("BerlinTestTrip")
                    print(Event, AllTasks)
            if event.type == pygame.MOUSEBUTTONDOWN:
                if HelpRect.collidepoint(event.pos):
                     MenuStatus = "Help menu 1"
                     Help()
def ButtonsForHelp(): # A seperate button interaction pathway for help buttons as they are housed on a different screen.
    global BackHelpRect
    global NextHelpRect
    global FinishHelpRect
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if BackHelpRect.collidepoint(event.pos): # Button navigaton.
                    if MenuStatus == "Help menu 1":
                        OpenMainMenu()
                    if MenuStatus == "Help menu 2":
                        MenuStatus = "Help menu 1"
                        Help()
                    if MenuStatus == "Help menu 3":
                        MenuStatus = "Help menu 2"
                        Help()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if NextHelpRect.collidepoint(event.pos): # Button navigaton.
                    if MenuStatus == "Help menu 1":
                        MenuStatus = "Help menu 2"
                        Help()
                    if MenuStatus == "Help menu 2":
                        MenuStatus = "Help menu 3"
                        Help()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if FinishHelpRect.collidepoint(event.pos): # Button navigaton.
                    if MenuStatus == "Help menu 3":
                        OpenMainMenu()

def CreateEvent():
    print ("Created")

def OpenEvent(EventSaveName):
    print ("Opened")
def Help():
    pygame.display.set_caption("Help Menu") # Naming the New Window.
    CurrentMenu = pygame.image.load(r'D:\Holiday Planner Screen Resources\Help Menu 1.jpg') # Opening a custom made Screen.
    Screen.blit(CurrentMenu, (0, 0))
    pygame.display.update()
    if MenuStatus == "Help menu 1":
        CurrentMenu = pygame.image.load(r'D:\Holiday Planner Screen Resources\Help Menu 1.jpg') # Opening a custom made Screen.
        Screen.blit(CurrentMenu, (0, 0))
        pygame.display.update()# Loads the menu Screen.
        BackHelp()
        NextHelp()
    if MenuStatus == "Help menu 2":
        CurrentMenu = pygame.image.load(r'D:\Holiday Planner Screen Resources\Help Menu 2.jpg') # Opening a custom made Screen.
        Screen.blit(CurrentMenu, (0, 0))
        pygame.display.update()# Loads the menu Screen.
        BackHelp()
        NextHelp()
    if MenuStatus == "Help menu 3":
        CurrentMenu = pygame.image.load(r'D:\Holiday Planner Screen Resources\Help Menu 3.jpg') # Opening a custom made Screen.
        Screen.blit(CurrentMenu, (0, 0))
        pygame.display.update()# Loads the menu Screen.
        BackHelp()
        FinishHelp()
    ButtonsForHelp()

# MAIN BODY

Screen = pygame.display.set_mode((824, 620))

OpenMainMenu()
pygame.display.update()

谢谢。

问题是主循环在定义之前引用了 BackHelpRect。复制它很容易,只需 select 第一个屏幕上的 "back" 菜单选项。为了调试这个,我在 BackHelp() 函数中添加了一个 print( "BackHelp Defined HERE" ) 。它并不总是事先调用。

要解决此问题,也许您的代码可以在菜单处理开始之前一次性定义所有这些图像和矩形。类似于:

def preloadButtons():
    global HelpButton, HelpButtonRect
    global BackHelpButton, BackHelpRect
    # etc. etc.

    HelpButton     = pygame.image.load('button.jpg') # Open the custom button design.
    HelpButton     = pygame.transform.scale(HelpButton, (151, 51))
    HelpButtonRect = HelpButton.get_rect()
    HelpButtonRect.topleft = (335, 415)

    BackHelpButton     = pygame.image.load('button.jpg') # Open the custom button design.
    BackHelpButton     = pygame.transform.scale(BackHelpButton, (235, 84))
    BackHelpButtonRect = BackHelpButton.get_rect()
    BackHelpButtonRect.topleft = (45, 490)

将所有这些按钮存储为单独的全局变量并不是一个很好的设计,它已经导致整个程序其余部分的绘图和事件测试变得复杂。最好将按钮的所有属性(图像、大小、位置、矩形)打包到一个数据结构中。它不一定是 Python class,只是将每个按钮属性放入 list 将是一个进步,然后也许所有这些列表都放入一个 [=18] =]列表。

例如,这里我们定义了一个按钮属性列表,然后遍历这些以创建一个更简单的按钮列表 name/image/rect。

help_button      = [ 'help', 'help_button.jpg', (151, 51), (335, 415) ]
back_help_button = [ 'back', 'back_button.jpg', (235, 84), ( 45, 490) ]
# ... TODO: rest of buttons
all_buttons_properties = [ help_button, back_help_button ]

# Initialise buttons
all_buttons = []
for butt in all_button_properties:
    button_image = pygame.image.load( butt[1] )                     # load
    button_image = pygame.transform.scale( button_image, butt[2] )  # resize
    button_rect  = button_image.get_rect()
    button_rect.topleft = butt[3]                                   # move
    all_buttons.append( butt[0], button_image, button_rect )

这为您提供了一个简单的 all_buttons 列表列表 [按钮名称、调整大小的按钮图像、预先定位的按钮矩形]。

可能您想要 if ... elif ... 对于这些按钮测试,而不是 if ... if ...:

        if event.type == pygame.MOUSEBUTTONDOWN:
            if NextHelpRect.collidepoint(event.pos): # Button navigaton.
                if MenuStatus == "Help menu 1":
                    MenuStatus = "Help menu 2"
                    Help()
                if MenuStatus == "Help menu 2":
                    MenuStatus = "Help menu 3"
                    Help()

MenuStatus 等于 "Help menu 1" 时会发生什么 -> 它变成 "Help menu 2",但紧接着下一个 if 再次改变这个 至 "Help menu 3"