使用for循环移动Pyglet精灵位置而非使用Pyglet时钟

0 投票
1 回答
1537 浏览
提问于 2025-04-18 09:24

我正在写我的第一个 pyglet 应用程序,用来可视化另一个脚本的计算结果。可惜我卡住了,不知道接下来该怎么做。

我想用一个循环把一个精灵从一个位置移动到另一个位置,所以在每次循环结束时,精灵的位置会根据上一个位置变化一个特定的距离,这个距离是循环计算出来的。

这是我正在写的代码的简化版本(希望这能帮助到有类似问题的人,然后我再复制我自己的具体项目)。

@window.event
def on_draw():
    window.clear()
    batch.draw()

def update(yd):
    Ball.y += yd

distance = [2,1,3,-2,-3,2,4,-5,1,2,3,-4,3,5,2,-2,3,2,3,-2,]

### test update in loop ###

for i in distance:
    time.sleep(0.1)
    update(i)


### Run app ##

pyglet.app.run()

我不想使用 pyglet.clock.schedule_interval(update()),因为循环的计算可能会比 clock.schedule 花更长的时间,这样移动就不会很流畅,但这没关系。

我遇到的问题是,在循环完成之前什么都不会发生,只有在 Python 完成循环后才会调用 pyglet.app.run(),但是如果我在循环之前调用 pyglet.app.run(),它只会在我关闭 pyglet 窗口后才运行循环。

1 个回答

1

在使用 pyglet 的时候,你并不能控制程序的主循环。

主循环是通过 pyglet.app.run() 启动的,你可以通过 window.event 装饰器来处理事件。

你在主循环启动之前运行你的循环,这就是为什么你会觉得什么都没有发生。

如果你想每0.1秒调用一次 update,你应该使用 clock.schedule_interval,这个方法需要一个要调用的函数和一个时间间隔参数。如果你想根据 distance 中的每个值移动你的精灵,你可以使用一个迭代器和一个嵌套函数,像这样:

def update():
   g = iter(distance)
   def inner(): 
       try:
           update(next(g))    
       except StopIteration:
           pass
   return inner

pyglet.clock.schedule_interval(update(), .1)

根据你的评论进行编辑:

给定你的循环:

for i in distance:
    time.sleep(0.1)
    update(i)

你可以把它变成一个迭代器:

def calculate():
    for i in distance:
        time.sleep(0.1) # just some expensive calculation
        yield i

然后在 on_draw() 中使用它:

calc = calculate()

@window.event
def on_draw():
    window.clear()
    batch.draw()
    try: update(next(calc)) 
    except StopIteration: pass

撰写回答