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

Pygame类方法中如何实现非阻塞定时执行操作

Pygame固定间隔执行操作非阻塞实现方案

time.sleep()会阻塞整个主线程,直接导致游戏渲染、事件响应全部卡住,绝对不能在Pygame主逻辑里用。游戏场景下最稳妥的实现方式是基于主循环帧时间差的计时方案,不需要开多线程,没有线程安全问题,完全不阻塞循环运行,是2D游戏开发的标准实现思路。


实现原理

Pygame自带的pygame.time.get_ticks()可以返回程序启动后经过的毫秒数,我们只需要给类增加两个记录变量:

  • 上一次执行目标方法的时间戳
  • 固定触发间隔(50秒对应50000毫秒)
    每次主循环运行时,比对当前时间和上次执行时间的差值,达到间隔就执行目标方法,同时更新上次执行的时间戳即可。整个判断过程耗时不到1微秒,完全不会拖慢运行效率。

现有代码的前置bug修正

在加计时逻辑前,先把原有代码里会导致功能失效的错误改了:

  1. 所有类的__init__方法漏写self参数(包括buildings、c_panel、monster),实例化时会直接报错
  2. town_hall内部自己新建了一个city实例,但主循环里渲染的是外部单独创建的town实例,加钱操作和显示的对象不是同一个,永远看不到金钱增长
  3. self.cit.add_money没加括号,只是引用了函数对象,根本没有实际执行加钱方法
  4. 主循环里pygame.display.update()和pygame.display.flip()功能重复,保留一个即可

具体修改代码

1. 修正基类定义

class buildings():
    def __init__(self):
        self.b_health = 100

class c_panel():
    def __init__(self):
        pass

class monster():
    def __init__(self):
        pass

2. 修改town_hall类,加入计时逻辑

class town_hall(buildings):
    def __init__(self, target_city):
        super().__init__() # 调用父类构造方法,继承b_health属性
        self.cit = target_city # 绑定外部传入的city实例,保证加钱和显示是同一个对象
        self.last_trigger_time = pygame.time.get_ticks() # 初始化上次触发时间为程序当前运行时间
        self.trigger_interval = 50 * 1000 # 触发间隔:50秒,单位为毫秒

    def adding_money(self):
        current_time = pygame.time.get_ticks()
        # 时间差达到间隔就执行加钱
        if current_time - self.last_trigger_time >= self.trigger_interval:
            self.cit.add_money() # 加括号才是实际调用方法
            self.last_trigger_time = current_time # 更新上次触发时间

3. 修改实例化代码,传入关联的city对象

town = city()
townhall = town_hall(town) # 把要加钱的town实例传入town_hall
citizen = citizens()

4. 主循环部分不需要大改,保留原有调用即可

while True:
    clock.tick(FPS)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
          
    gamedisplay.fill(WHITE)
    citizen.draw(gamedisplay)
    citizen.c_mousedrag()
    citizen.c_raidfight()
    townhall.adding_money() # 这个方法现在只会做时间判断,到点才加钱,不会阻塞
    town.draw(gamedisplay)
    
    pygame.display.flip() # 删掉重复的update调用

不推荐多线程方案的原因

虽然用threading.Timer也能实现定时,但Pygame的渲染、对象属性读写都不是线程安全的,跨线程修改money属性偶尔会出现和渲染逻辑的竞态问题,导致随机崩溃或者显示异常,对于这种简单的定时需求完全没必要引入多线程复杂度。

这个方案的时间误差最多为1帧时长,设置FPS为30时误差不超过33毫秒,对于50秒的触发间隔来说完全感知不到,稳定性远高于多线程方案。

内容的提问来源于stack exchange,提问作者loudmounth artist

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:36:25