我听说协同程序是构建游戏的好方法(例如,PEP 342:“协同程序是表达许多算法的自然方式,例如模拟、游戏......”)但我很难包装我的看看这实际上是如何完成的。
我从这篇文章中看到协程可以表示状态机中的状态,这些状态使用调度程序相互转换,但我不清楚这如何应用于游戏状态根据多个玩家的移动而变化的游戏。
有没有使用协程编写的游戏的简单示例?或者有人可以提供一个如何完成的草图吗?
协程允许创建大量具有协作多任务处理的非常轻量级的“微线程”(即微线程故意挂起自己以允许其他微线程运行)。阅读 Dave Beazley关于这个主题的文章。
现在,很明显这种微线程对游戏编程有什么用处。考虑一个实时战略游戏,你有几十个单位——每个单位都有自己的想法。在模拟的多任务处理环境中,每个单元的 AI 作为微线程运行可能是一种方便的抽象。这只是一个例子,我相信还有更多。
Google 上的“协程游戏编程”搜索似乎带来了有趣的结果。
协程最突出的例子可能是旧的图形点击冒险游戏,它们用于编写游戏中的过场动画和其他动画序列。一个简单的代码示例如下所示:
# script_file.scr
bob.walkto(jane)
bob.lookat(jane)
bob.say("How are you?")
wait(2)
jane.say("Fine")
...
这整个序列不能写成普通代码,因为你想看到鲍勃在你做完他的步行动画bob.walkto(jane)
而不是直接跳到下一行。但是,要播放步行动画,您需要将控制权交还给游戏引擎,这就是协程发挥作用的地方。
整个序列作为协程执行,这意味着您可以根据需要暂停和恢复它。像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()
然而,一个小小的警告,虽然协程使这些序列的编码变得非常简单,但并不是每个你会发现它们的实现都会考虑到序列化,所以如果你大量使用协程,游戏保存将成为一个相当麻烦的问题。
这个例子也只是游戏中协程最基本的例子,协程本身也可以用于许多其他任务和算法。
可以在游戏中使用协程的一种方式是在 Actor 之类的模型中作为轻量级线程,例如在Kamaelia中。
游戏中的每个对象都是 Kamaelia 的“组件”。组件是一个对象,它可以通过在允许暂停时产生来暂停执行。这些组件还有一个消息传递系统,允许它们安全地异步地相互通信。
所有对象将同时做自己的事情,并在交互发生时相互发送消息。
因此,它并不是真正特定于游戏,但是当您有大量通信组件同时执行时,任何事情都可以从协程中受益。
您可能会觉得有趣的两个链接:
http://aigamedev.com/open/articles/coroutine-state-machine/
http://www.dabeaz.com/coroutines/(在此页面和 pdf 中搜索“任务”)
希望使用协程来表示单个演员 AI 脚本是很常见的。不幸的是,人们倾向于忘记协程与线程具有相同的同步和互斥问题,只是在更高级别。因此,您通常需要首先尽可能多地消除本地状态,然后编写健壮的方法来处理协程中当您所指的内容不复存在时出现的错误。
所以在实践中它们很难从中受益,这就是为什么像 UnrealScript 这样使用一些协同程序外观的语言将许多有用的逻辑推向原子事件的原因。有些人从中获得了很好的效用,例如。EVE Online 的人,但他们几乎必须围绕这个概念来构建他们的整个系统。(以及他们如何处理共享资源的争用并没有很好的记录。)