You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 17:54:06