Python Pygame开发:游戏菜单无法显示问题求助
问题排查:Lunar Dungeon菜单无法显示的原因及修复方案
嘿,我来帮你看看菜单不显示的问题!仔细梳理你的代码后,找到了核心问题和几个需要调整的细节,具体如下:
核心原因:菜单逻辑从未被触发
你在代码后半部分定义了Game类,但从头到尾都没有创建这个类的实例,也没有启动菜单的显示逻辑。而且前面的while running循环是无限运行的(直到你关闭窗口),这就导致后面的Game类代码完全没机会被执行——程序一直卡在蓝色背景的循环里,菜单自然不会出现。
其他需要修正的细节
- 重复初始化Pygame:代码开头已经调用了
pygame.init(),但Game类的__init__里又重复调用,会造成冗余甚至潜在问题。 - 窗口大小不一致:开头创建的窗口是1080x720,但
Game类里又创建了480x270的窗口,会导致窗口切换混乱。 - 缺少菜单基础类:
Game类里引用了MainMenu、OptionsMenu、CreditsMenu,但代码里没有定义这些类,就算启动菜单也会报错。
修复后的完整代码
我帮你调整了代码,解决了上述问题,现在菜单可以正常显示并交互了:
import pygame import sys # 初始化Pygame(只做一次) pygame.init() print(pygame.ver) # 定义菜单基础类(Game类依赖这些,必须补上) class Menu(): def __init__(self, game): self.game = game self.run_display = True self.cursor_rect = pygame.Rect(0, 0, 20, 20) self.offset = -100 def draw_cursor(self): self.game.draw_text('>', 15, self.cursor_rect.x, self.cursor_rect.y) def blit_screen(self): self.game.window.blit(self.game.display, (0, 0)) pygame.display.update() self.game.reset_keys() class MainMenu(Menu): def __init__(self, game): Menu.__init__(self, game) self.state = "Start" self.startx, self.starty = self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 - 40 self.optionsx, self.optionsy = self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 self.creditsx, self.creditsy = self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 + 40 self.cursor_rect.midtop = (self.startx + self.offset, self.starty) def display_menu(self): self.run_display = True while self.run_display: self.game.check_events() self.check_input() self.game.display.fill(self.game.BLACK) self.game.draw_text('LUNAR DUNGEON', 25, self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 - 80) self.game.draw_text("Start Game", 20, self.startx, self.starty) self.game.draw_text("Options", 20, self.optionsx, self.optionsy) self.game.draw_text("Credits", 20, self.creditsx, self.creditsy) self.draw_cursor() self.blit_screen() def move_cursor(self): if self.game.DOWN_KEY: if self.state == 'Start': self.cursor_rect.midtop = (self.optionsx + self.offset, self.optionsy) self.state = 'Options' elif self.state == 'Options': self.cursor_rect.midtop = (self.creditsx + self.offset, self.creditsy) self.state = 'Credits' elif self.state == 'Credits': self.cursor_rect.midtop = (self.startx + self.offset, self.starty) self.state = 'Start' elif self.game.UP_KEY: if self.state == 'Start': self.cursor_rect.midtop = (self.creditsx + self.offset, self.creditsy) self.state = 'Credits' elif self.state == 'Options': self.cursor_rect.midtop = (self.startx + self.offset, self.starty) self.state = 'Start' elif self.state == 'Credits': self.cursor_rect.midtop = (self.optionsx + self.offset, self.optionsy) self.state = 'Options' def check_input(self): self.move_cursor() if self.game.START_KEY: if self.state == 'Start': self.game.playing = True elif self.state == 'Options': self.game.curr_menu = self.game.options elif self.state == 'Credits': self.game.curr_menu = self.game.credits self.run_display = False class OptionsMenu(Menu): def __init__(self, game): Menu.__init__(self, game) self.state = "Volume" self.volx, self.voly = self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 - 40 self.backx, self.backy = self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 + 40 self.cursor_rect.midtop = (self.volx + self.offset, self.voly) def display_menu(self): self.run_display = True while self.run_display: self.game.check_events() self.check_input() self.game.display.fill(self.game.BLACK) self.game.draw_text('OPTIONS', 25, self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 - 80) self.game.draw_text("Volume", 20, self.volx, self.voly) self.game.draw_text("Back", 20, self.backx, self.backy) self.draw_cursor() self.blit_screen() def check_input(self): if self.game.BACK_KEY: self.game.curr_menu = self.game.main_menu self.run_display = False elif self.game.START_KEY: # 这里可以后续添加音量调整逻辑 pass self.move_cursor() def move_cursor(self): if self.game.DOWN_KEY: if self.state == 'Volume': self.cursor_rect.midtop = (self.backx + self.offset, self.backy) self.state = 'Back' elif self.state == 'Back': self.cursor_rect.midtop = (self.volx + self.offset, self.voly) self.state = 'Volume' elif self.game.UP_KEY: if self.state == 'Volume': self.cursor_rect.midtop = (self.backx + self.offset, self.backy) self.state = 'Back' elif self.state == 'Back': self.cursor_rect.midtop = (self.volx + self.offset, self.voly) self.state = 'Volume' class CreditsMenu(Menu): def __init__(self, game): Menu.__init__(self, game) def display_menu(self): self.run_display = True while self.run_display: self.game.check_events() if self.game.BACK_KEY or self.game.START_KEY: self.game.curr_menu = self.game.main_menu self.run_display = False self.game.display.fill(self.game.BLACK) self.game.draw_text('CREDITS', 25, self.game.DISPLAY_W/2, self.game.DISPLAY_H/2 - 80) self.game.draw_text('Made with Pygame', 15, self.game.DISPLAY_W/2, self.game.DISPLAY_H/2) self.blit_screen() # 主游戏类 class Game(): def __init__(self): self.running, self.playing = True, False self.UP_KEY, self.DOWN_KEY, self.START_KEY, self.BACK_KEY = False, False, False, False self.DISPLAY_W, self.DISPLAY_H = 1080, 720 # 统一窗口大小 self.display = pygame.Surface((self.DISPLAY_W,self.DISPLAY_H)) self.window = pygame.display.set_mode((self.DISPLAY_W,self.DISPLAY_H)) pygame.display.set_caption("Lunar Dungeon") # 加载图标并增加异常处理 try: icon = pygame.image.load('moon.png') pygame.display.set_icon(icon) except: print("Warning: moon.png not found, using default icon") # 字体容错处理 self.font_name = '8-BIT WONDER.TTF' if not pygame.font.match_font(self.font_name.split('.')[0]): self.font_name = pygame.font.get_default_font() self.BLACK, self.WHITE = (0, 0, 0), (255, 255, 255) self.main_menu = MainMenu(self) self.options = OptionsMenu(self) self.credits = CreditsMenu(self) self.curr_menu = self.main_menu def game_loop(self): while self.playing: self.check_events() if self.START_KEY: self.playing = False self.display.fill(self.BLACK) self.draw_text('Game Started! Press ENTER to return to menu', 20, self.DISPLAY_W/2, self.DISPLAY_H/2) self.window.blit(self.display, (0,0)) pygame.display.update() self.reset_keys() def check_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: self.running, self.playing = False, False self.curr_menu.run_display = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_RETURN: self.START_KEY = True if event.key == pygame.K_BACKSPACE: self.BACK_KEY = True if event.key == pygame.K_DOWN: self.DOWN_KEY = True if event.key == pygame.K_UP: self.UP_KEY = True def reset_keys(self): self.UP_KEY, self.DOWN_KEY, self.START_KEY, self.BACK_KEY = False, False, False, False def draw_text(self, text, size, x, y ): font = pygame.font.Font(self.font_name,size) text_surface = font.render(text, True, self.WHITE) text_rect = text_surface.get_rect() text_rect.center = (x,y) self.display.blit(text_surface,text_rect) # 启动游戏入口 if __name__ == "__main__": lunar_game = Game() while lunar_game.running: lunar_game.curr_menu.display_menu() lunar_game.game_loop() pygame.quit() sys.exit()
关键修复点说明
- 补全菜单类:添加了
Menu基类和三个具体菜单类,让菜单逻辑可以正常运行。 - 移除冗余初始化:只在代码开头做一次Pygame初始化,避免重复操作。
- 统一窗口大小:把
Game类的窗口大小改成和初始窗口一致的1080x720,避免窗口切换问题。 - 添加启动逻辑:在代码末尾实例化
Game类并启动菜单循环,让菜单终于能被执行到。 - 增加容错处理:包括字体和图标加载的异常处理,避免程序崩溃。
现在运行代码,你就能看到正常显示的主菜单了,用上下方向键切换选项,回车键确认,退格键返回哦!
内容的提问来源于stack exchange,提问作者user17025844
相关产品推荐
相关产品推荐

