游戏设计的协程?

发布于 2024-07-30 10:06:57 字数 376 浏览 6 评论 0原文

我听说协程是构建游戏的好方法(例如 PEP 342:“协程是表达许多算法的自然方式,例如模拟、游戏......”)但我很难理解这实际上是如何完成的。

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

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

I've heard that coroutines are a good way to structure games (e.g., PEP 342: "Coroutines are a natural way of expressing many algorithms, such as simulations, games...") but I'm having a hard time wrapping my head around how this would actually be done.

I see from this article that coroutines can represent states in a state machine which transition to each other using a scheduler, but it's not clear to me how this applies to a game where the game state is changing based on moves from multiple players.

Is there any simple example of a game written using coroutines available? Or can someone offer a sketch of how it might be done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

多像笑话 2024-08-06 10:06:57

协程允许通过协作多任务创建大量非常轻量级的“微线程”(即微线程故意挂起自身以允许其他微线程运行)。 请阅读 Dave Beazley 关于此主题的文章

现在,这种微线程对于游戏编程的作用显而易见。 考虑一款实时策略游戏,其中有数十个单位 - 每个单位都有自己的思想。 对于每个单元的人工智能来说,在模拟的多任务环境中作为这样的微线程运行可能是一种方便的抽象。 这只是一个例子,我相信还有更多。

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

Coroutines allow for creating large amounts of very-lightweight "microthreads" with cooperative multitasking (i.e. microthreads suspending themselves willfully to allow other microthreads to run). Read up in Dave Beazley's article on this subject.

Now, it's obvious how such microthreads can be useful for game programming. Consider a realtime strategy game, where you have dozens of units - each with a mind of its own. It may be a convenient abstraction for each unit's AI to run as such a microthread in your simulated multitasking environment. This is just one example, I'm sure there are more.

The "coroutine game programming" search on Google seems to bring up interesting results.

戒ㄋ 2024-08-06 10:06:57

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

# 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()

然而,有一点警告,虽然协程使这些序列的编码非常简单,但并不是您发现的每个实现都会考虑到序列化而构建,因此游戏保存将如果大量使用协程,这将成为一个相当麻烦的问题。

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

The most prominent case of coroutines are probally old graphical point&click adventure games, where they where used to script cutscenes and other animated sequences in the game. A simple code example would look like this:

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

This whole sequence can't be written as normal code, as you want to see bob do his walk animation after you did bob.walkto(jane) instead of jumping right to the next line. For the walk animation to play you however need to give control back to the game engine and that is where coroutines come into play.

This whole sequence is executed as a coroutine, meaning you have the ability to suspend and resume it as you like. A command like bob.walkto(jane) thus tells the engine side bob object its target and then suspends the coroutine, waiting for a wakeup call when bob has reached his target.

On the engine side things might look like this (pseudo code):

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()

A litte word of warning however, while coroutines make coding these sequences very simple, not every implementations you will find of them will be build with serialisation in mind, so game saving will become quite a troublesome issue if you make heavy use of coroutines.

This example is also just the most basic case of a coroutine in a game, coroutines themselves can be used for plenty of other tasks and algorithms as well.

听你说爱我 2024-08-06 10:06:57

协程在游戏中的一种使用方式是在类似角色的模型中作为轻量级线程,例如在 Kamaelia 中。

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

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

因此,它并不是真正特定于游戏,但是当您有大量同时运行的通信组件时,任何事情都可以从协程中受益。

One way coroutines can be used in games is as light weight threads in an actor like model, like in Kamaelia.

Each object in your game would be a Kamaelia 'component'. A component is an object that can pause execution by yielding when it's allowable to pause. These components also have a messaging system that allows them to safely communicate to each other asynchronously.

All the objects would be concurrently doing their own thing, with messages sent to each other when interactions occur.

So, it's not really specific to games, but anything when you have a multitude of communicating components acting concurrently could benefit from coroutines.

扶醉桌前 2024-08-06 10:06:57

使用协程来表示单个参与者的 AI 脚本是很常见的。 不幸的是,人们往往忘记协程具有与线程相同的同步和互斥问题,只是级别更高。 因此,您通常需要首先尽可能地消除本地状态,然后编写可靠的方法来处理协程中当您所指的内容不再存在时出现的错误。

因此,在实践中,它们很难从中受益,这就是为什么像 UnrealScript 这样使用某种协程外观的语言将大部分有用的逻辑推向原子事件的原因。 有些人从中获得了很好的效用,例如。 EVE Online 的人员,但他们必须围绕这个概念构建整个系统。 (并且他们如何处理共享资源的争用没有很好的记录。)

It is quite common to want to use coroutines to represent individual actor AI scripts. Unfortunately people tend to forget that coroutines have all the same synchronisation and mutual exclusion problems that threads have, just at a higher level. So you often need to firstly do as much as you can to eliminate local state, and secondly write robust ways to handle the errors in a coroutine that arise when something you were referring to ceases to exist.

So in practice they are quite hard to get a benefit from, which is why languages like UnrealScript that use some semblance of coroutines push much of the useful logic out to atomic events. Some people get good utility out of them, eg. the EVE Online people, but they had to pretty much architect their entire system around the concept. (And how they handle contention over shared resources is not well documented.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文