Python 游戏设计的协同程序?

Python 游戏设计的协同程序?,python,coroutine,Python,Coroutine,我听说协同程序是构建游戏的一种很好的方式(例如:“协同程序是表达许多算法的一种自然方式,例如模拟、游戏……”),但我很难理解这到底是如何实现的 我从中看到,协同程序可以表示状态机中的状态,这些状态机使用调度程序相互转换,但我不清楚这如何适用于游戏状态根据多个玩家的移动而变化的游戏 有没有使用协同程序编写的简单游戏示例?或者有人可以提供一个如何完成的草图吗?两个您可能会感兴趣的链接: (在此页面和pdf中搜索“任务”)协同程序允许创建大量具有协作多任务功能的非常轻量级的“微线程”(即微线程随意挂

我听说协同程序是构建游戏的一种很好的方式(例如:“协同程序是表达许多算法的一种自然方式,例如模拟、游戏……”),但我很难理解这到底是如何实现的

我从中看到,协同程序可以表示状态机中的状态,这些状态机使用调度程序相互转换,但我不清楚这如何适用于游戏状态根据多个玩家的移动而变化的游戏


有没有使用协同程序编写的简单游戏示例?或者有人可以提供一个如何完成的草图吗?

两个您可能会感兴趣的链接:


(在此页面和pdf中搜索“任务”)

协同程序允许创建大量具有协作多任务功能的非常轻量级的“微线程”(即微线程随意挂起以允许其他微线程运行)。阅读戴夫·比兹利关于这个问题的文章

现在,很明显,这样的微线程对于游戏编程是多么有用。考虑一个实时战略游戏,你有几十个单位,每个人都有自己的想法。对于每个单元的AI来说,在模拟多任务环境中作为微线程运行可能是一种方便的抽象。这只是一个例子,我相信还有更多


谷歌上的“协同程序游戏编程”搜索似乎带来了有趣的结果。

在游戏中使用协同程序的一种方法是在类似于演员的模型中使用轻量级线程,如中

游戏中的每个对象都是Kamaelia的“组件”。组件是一个对象,它可以在允许暂停时通过让步来暂停执行。这些组件还有一个消息传递系统,允许它们安全地异步通信

所有对象都将同时做自己的事情,当交互发生时,消息会互相发送


因此,这并不是真正针对游戏的,但是当你有大量的通信组件同时运行时,任何东西都可以从协同程序中受益。

协同程序最突出的例子可能是古老的图形点击冒险游戏,它们用于在游戏中编写剪接场景和其他动画序列。一个简单的代码示例如下所示:

# script_file.scr
bob.walkto(jane)
bob.lookat(jane)
bob.say("How are you?")
wait(2)
jane.say("Fine")
...
整个序列不能作为普通代码编写,因为您希望看到bob在执行
bob.walkto(jane)
之后执行他的行走动画,而不是直接跳到下一行。然而,要播放行走动画,您需要将控制权交还给游戏引擎,这就是协同程序发挥作用的地方

整个序列作为协同程序执行,这意味着您可以根据需要暂停和恢复它。因此,类似于
bob.walkto(jane)
的命令会将其目标告知引擎端bob对象,然后暂停协同程序,等待bob到达目标时的唤醒调用

在引擎端,情况可能如下所示(伪代码):

不过,有一点警告,虽然协同程序使这些序列的编码变得非常简单,但并不是所有的实现都是在考虑序列化的情况下构建的,因此如果大量使用协同程序,保存游戏将成为一个相当麻烦的问题


这个例子也是游戏中协同程序的最基本情况,协同程序本身也可以用于许多其他任务和算法。

使用协同程序来表示单个演员AI脚本是很常见的。不幸的是,人们往往忘记了协同程序与线程在更高层次上有着相同的同步和互斥问题。因此,您通常需要首先尽可能多地消除局部状态,然后编写健壮的方法来处理协同程序中的错误,这些错误是在您所引用的内容不再存在时出现的


因此,在实践中,它们很难从中获益,这就是为什么像UnrealScript这样的语言使用了一些相似的协同程序,将许多有用的逻辑推到了原子事件上。有些人从他们身上获得了很好的效用,例如EVE在线人,但他们必须围绕这个概念构建整个系统。(它们如何处理共享资源上的争用还没有很好的文档。)

协同路由存在一些同步问题,但前提是它们的状态在yield()调用之间不一致。在yield()调用之间的所有代码周围都有一个隐式锁可以大大简化事情。最大的问题是,无论何时创建例程,都应该决定该例程是否总是能够在它产生()之前完成。如果例程的调用者不希望例程产生,那么在调用例程时,它可能没有处于一致状态的东西。添加yield()将是一个突破性的改变。问题是,您通常希望能够在所有地方都让这样的例程发挥任何作用(如在UnrealScript中,“潜在函数”隐式地产生),但这会导致协同例程的组合以不可预知的方式交互。如果一个是巡逻队,说“往北走;看;往南走;看;重复”;另一个是反应程序,说“如果(从西边听到的声音){往西走;看;往东走;}”,那么这两个动作的交错可能导致演员的动作相当不可预测。这就是为什么UnrealScript只允许在一个“协同程序”中使用这些函数的原因。即使每个参与者只有一个协同程序,这仍然不足以确保逻辑在语言级别始终有效:如果您的协同程序说:“拔出剑;等待1秒;用剑攻击对手”如果你被另一个玩家解除了武装,剑消失了怎么办?特别是,如果您的语言通过对现在引用空对象的剑使用局部变量来实现该协程,该怎么办?信息技术
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()