游戏设计中的协程?

16 投票
5 回答
4183 浏览
提问于 2025-04-15 13:27

我听说协程是构建游戏的好方法(比如,PEP 342提到:“协程是表达许多算法的自然方式,比如模拟、游戏…”),但我还是很难理解这到底是怎么实现的。

我从这篇文章中看到,协程可以表示状态机中的状态,并通过调度器相互转换,但我不太明白这如何适用于一个游戏,因为游戏状态是根据多个玩家的动作而变化的。

有没有简单的例子,展示用协程写的游戏?或者有人能简单描述一下这可能是怎么做的吗?

5 个回答

10

最常见的协程应用可能是在老式的图形点选冒险游戏中,它们被用来编写过场动画和其他游戏中的动画序列。一个简单的代码示例看起来是这样的:

# script_file.scr
bob.walkto(jane)
bob.lookat(jane)
bob.say("How are you?")
wait(2)
jane.say("Fine")
...

这个整个动画序列不能像普通代码那样写,因为你希望在执行完 bob.walkto(jane) 之后看到 bob 的走路动画,而不是直接跳到下一行。为了让走路动画播放,你需要把控制权交还给游戏引擎,这就是协程发挥作用的地方。

这个整个序列是作为一个协程来执行的,这意味着你可以随时暂停和恢复它。像 bob.walkto(jane) 这样的命令告诉引擎中的 bob 对象它的目标,然后暂停协程,等待 bob 到达目标时的唤醒信号。

在引擎那边,事情可能看起来像这样(伪代码):

class Script:
    def __init__(self, filename):
        self.coroutine  = Coroutine(filename)
        self.is_wokenup = True

    def wakeup(self):
        self.is_wokenup = False;

    def update():
        if self.is_wokenup:
          coroutine.run()            


class Character:
   def walkto(self, target, script):
       self.script = script
       self.target = target

   def update(self):
       if target:
           move_one_step_closer_to(self.target)
           if close_enough_to(self.target):
               self.script.wakeup()

               self.target = None
               self.script = None

objects = [Character("bob"), Character("jane")]
scripts = [Script("script_file.scr")]

while True:
    for obj in objects:
        obj.update()

    for scr in scripts:
        scr.update()

不过要提醒一下,虽然协程让编写这些序列变得非常简单,但并不是所有的实现都考虑到了序列化,所以如果你大量使用协程,游戏存档可能会变得相当麻烦。

这个例子只是游戏中协程的最基本用法,实际上,协程还可以用于很多其他任务和算法。

10

协程让我们可以创建很多非常轻量级的“微线程”,并且这些微线程可以进行合作式的多任务处理(也就是说,微线程可以主动暂停自己,让其他微线程运行)。如果想了解更多,可以看看Dave Beazley的文章

这种微线程在游戏编程中显然非常有用。想象一下一个实时战略游戏,里面有很多单位,每个单位都有自己的思考方式。在这种情况下,让每个单位的人工智能作为微线程在你模拟的多任务环境中运行,可能会非常方便。这只是一个例子,肯定还有更多的应用。

在谷歌上搜索“协程游戏编程”似乎会出现一些有趣的结果。

7

在游戏中,一种使用协程的方法是把它们当作轻量级线程,像在Kamaelia这样的演员模型。

游戏中的每个对象都可以看作是一个Kamaelia的“组件”。这个组件是一个可以在允许暂停的时候暂停执行的对象。组件之间还有一个消息系统,可以让它们安全地异步交流。

所有的对象可以同时各自做自己的事情,当发生互动时,它们会互相发送消息。

所以,这种方法不仅仅适用于游戏,任何有很多组件同时交流的场景都可以从协程中受益。

撰写回答