使用Pygame开发2D平台游戏运行10秒后卡顿变慢该如何解决?
问题根源
你的卡顿问题核心是代码逻辑导致的内存与渲染负载持续升高,具体有以下几点:
- 每帧重复创建环境元素:主游戏循环内反复调用
environment.make_block()、environment.make_sprite(),这两个函数会向全局列表追加新的Surface对象,不会清理旧数据。25FPS的帧率下每秒新增25个方块、25个精灵,运行10秒后就有数百个对象需要渲染、参与碰撞检测,性能自然会持续下降。 - 碰撞检测逻辑错误:玩家类的跳跃方法中,遍历方块判断碰撞时,只要后续遍历到未碰撞的方块,就会把前面的碰撞结果覆盖为
False,只有列表最后一个方块的碰撞判定是有效的,会导致落地逻辑异常。 - 循环导入:main.py导入player模块,player.py又导入main的全部内容,会触发不必要的初始化逻辑,存在隐性风险。
- 重复加载图片资源:
make_sprite每次调用都会重新读取本地图片文件,IO操作本身耗时,也会额外占用内存。
修复方案
1. 修改main.py
把环境创建逻辑从游戏循环中移出,仅在初始化阶段执行一次即可:
import pygame import player import environment def run_game(): pygame.init() winW, winH = 900, 650 screen = pygame.display.set_mode((winW, winH)) pygame.display.set_caption(" ") icon = pygame.Surface((32, 32)) icon.fill((255, 255, 255)) pygame.display.set_icon(icon) character = player.Player() clock = pygame.time.Clock() FPS = 25 # 环境仅初始化一次,不要放在循环里 environment.make_block(1000, 32, 50, 500, (255, 255, 255)) environment.make_sprite(64, 64, 200, 100, "Grass Block 16x.png") running = True while running: clock.tick(FPS) print(clock.get_fps()) screen.fill((50, 100, 100)) screen.blit(character.surf, character.rect) character.jump() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: running = False # Get Pressed Keys keys = pygame.key.get_pressed() # Check if the player should be moving if keys[pygame.K_LEFT]: character.rect.move_ip(-6, 0) if keys[pygame.K_RIGHT]: character.rect.move_ip(6, 0) if keys[pygame.K_UP] and character.on_ground: character.jumping = True else: character.jumping = False for i in range(len(environment.block_surf_list)): screen.blit(environment.block_surf_list[i], environment.block_rect_list[i]) for i in range(len(environment.sprite_list)): screen.blit(environment.sprite_list[i], environment.sprite_rect_list[i]) pygame.display.flip() if __name__ == "__main__": run_game()
2. 修改player.py
删除循环导入的语句,修复碰撞检测逻辑:
import pygame import environment # 删掉from main import *的语句,避免循环导入 class Player(pygame.sprite.Sprite): def __init__(self, w=32, h=32): super(Player, self).__init__() self.surf = pygame.Surface((w, h)) self.rect = self.surf.get_rect() self.surf.fill((255, 0, 0)) self.jumping = False self.on_ground = False self.fall_speed = 3 self.air_time = 0 self.jump_height = 30 def jump(self): if self.jumping and self.air_time <= 5: self.rect.y -= self.jump_height self.fall_speed = 0 self.air_time += 1 else: # 修复碰撞检测逻辑:只要碰到任意一个方块就判定在地面 self.on_ground = False for i in range(len(environment.block_rect_list)): if self.rect.colliderect(environment.block_rect_list[i]): self.on_ground = True self.air_time = 0 break if not self.on_ground: self.rect.y += self.fall_speed self.fall_speed += 2
3. 优化environment.py(可选)
可以增加图片缓存逻辑,避免重复加载相同资源,也可以加重置环境的方法方便后续场景切换:
import pygame block_surf_list = [] block_rect_list = [] # 增加图片缓存字典 img_cache = {} def make_block(width, height, x_pos, y_pos, block_color): block_surf = pygame.Surface((width, height)) block_surf.fill(block_color) block_rect = block_surf.get_rect() block_rect.move_ip(x_pos, y_pos) block_surf_list.append(block_surf) block_rect_list.append(block_rect) sprite_list = [] sprite_rect_list = [] test_size_1 = 32 def make_sprite(width, height, x_pos, y_pos, sprite_path): # 图片已经加载过就直接用缓存 if sprite_path in img_cache: block_image = img_cache[sprite_path] else: block_image = pygame.image.load(sprite_path) img_cache[sprite_path] = block_image block_image = pygame.transform.scale(block_image, (width, height)) block_image_rect = block_image.get_rect() block_image_rect.move_ip(x_pos, y_pos) sprite_list.append(block_image) sprite_rect_list.append(block_image_rect)
修改完成后运行游戏,卡顿问题就会完全解决,落地判定也会恢复正常。
内容的提问来源于stack exchange,提问作者Luca-Fly
相关产品推荐
相关产品推荐

