如何在Python类中实现Pygame游戏加载屏与资源加载并行运行?
实现Pygame加载资源时同步显示动画加载屏
嘿,我明白你想实现的是加载资源时同步展示动画加载屏的需求,用multiprocessing确实容易踩坑——因为Pygame的渲染上下文是绑定在主线程的,子进程没法直接操作窗口,很容易出现崩溃或者动画不显示的问题。下面给你两种靠谱的实现思路,都能完美搞定这个需求:
方法一:使用threading线程(推荐)
把资源加载逻辑放到子线程中执行,主线程专注于渲染加载屏动画,通过共享变量来跟踪加载进度,这样两者就能同时运行了。
完整代码示例
import pygame import threading import time class Game: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((800, 600)) self.clock = pygame.time.Clock() self.loading_done = False self.loading_progress = 0 # 加载进度0-100 # 启动资源加载线程 self.load_thread = threading.Thread(target=self.load_assets) self.load_thread.start() # 主线程运行加载屏动画 self.loading_screen() # 加载完成后进入游戏主循环 self.main_game_loop() def loading_screen(self): while not self.loading_done: # 处理退出事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() # 绘制加载屏背景 self.screen.fill((30, 30, 30)) # 绘制进度条(示例动画) bar_width = 400 bar_height = 40 progress_width = int(bar_width * (self.loading_progress / 100)) pygame.draw.rect(self.screen, (60, 60, 60), (200, 280, bar_width, bar_height)) pygame.draw.rect(self.screen, (0, 255, 0), (200, 280, progress_width, bar_height)) # 绘制加载文本 font = pygame.font.Font(None, 36) text = font.render(f"Loading... {self.loading_progress}%", True, (255, 255, 255)) self.screen.blit(text, (320, 230)) # 更新屏幕 pygame.display.flip() self.clock.tick(60) # 保持60帧 def load_assets(self): # 模拟加载大资源,实际替换成你的资源加载逻辑 assets_to_load = ["texture1.png", "sound1.wav", "level1.json", "font.ttf"] total_assets = len(assets_to_load) for idx, asset in enumerate(assets_to_load): # 这里替换成真实的资源加载代码,比如pygame.image.load()等 print(f"Loading {asset}...") time.sleep(0.5) # 模拟加载耗时 # 更新加载进度 self.loading_progress = int((idx + 1) / total_assets * 100) # 标记加载完成 self.loading_done = True def main_game_loop(self): print("进入游戏主循环!") running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False self.screen.fill((0, 0, 255)) font = pygame.font.Font(None, 48) text = font.render("游戏加载完成!", True, (255, 255, 255)) self.screen.blit(text, (250, 270)) pygame.display.flip() self.clock.tick(60) pygame.quit() if __name__ == "__main__": Game()
关键注意点
- 用
threading.Thread把load_assets放到子线程,避免阻塞主线程的渲染 - 通过
self.loading_done和self.loading_progress两个共享变量同步状态,这两个变量是线程安全的(因为只是简单的赋值和读取操作) - 主线程在
loading_screen中持续处理事件、渲染动画,直到loading_done变为True
方法二:分帧加载资源(无线程,适合简单场景)
如果不想用线程,可以把资源加载拆分成多个小步骤,每帧加载一小部分,同时更新加载屏动画。这种方法完全在主线程运行,没有线程安全问题。
简化代码示例
import pygame class Game: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((800, 600)) self.clock = pygame.time.Clock() self.asset_loader = self.load_assets_generator() self.loading_done = False self.loading_screen() self.main_game_loop() def loading_screen(self): while not self.loading_done: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() # 执行一次资源加载步骤 try: progress = next(self.asset_loader) except StopIteration: self.loading_done = True break # 绘制加载屏动画 self.screen.fill((30, 30, 30)) font = pygame.font.Font(None, 36) text = font.render(f"Loading... {progress}%", True, (255, 255, 255)) self.screen.blit(text, (320, 270)) pygame.display.flip() self.clock.tick(60) def load_assets_generator(self): # 用生成器分步骤加载资源,每一步返回当前进度 assets = ["img1.png", "sound1.wav", "map1.dat"] total = len(assets) for i, asset in enumerate(assets): # 真实加载逻辑 # img = pygame.image.load(asset) # self.assets.append(img) yield int((i+1)/total * 100) def main_game_loop(self): # 游戏主逻辑 pass if __name__ == "__main__": Game()
为什么不推荐multiprocessing?
Pygame的图形渲染依赖于主线程的SDL上下文,子进程无法直接访问这个上下文,强行在子进程中操作Pygame窗口会导致崩溃、无响应或者动画不显示的问题。所以线程或者分帧加载是更稳妥的方案。
内容的提问来源于stack exchange,提问作者CFLS
相关产品推荐
相关产品推荐

