是否有必要与主要代码分开实施游戏机制/规则?


25

不知道它是否适合这个社区的范围,还是应该去Stackoverflow。

让我们假设我希望我的游戏可以在其核心中轻松扩展,即,我希望很多人,即使没有扎实的编程知识,也能够不仅调整现有规则,而且甚至可以添加全新的游戏机制。我本人不是一个优秀的程序员,但是我已经准备好学习,我只需要一些指导和保证就可以做到。

我想到的是,是否有可能/可行地以某种方式与主要实用程序代码分开实施游戏机制?我的意思是,对于桌面游戏,我们有那些规则手册,其中没有包含所有动作的实际算法,而是描述了一些协议和限制,并大量引用了每个此类规则的上下文。是否有可能针对PC游戏做一些类似的事情,例如用人类编程语言以某种非常高级的,易于理解(且可更改)的方式描述所有规则,然后将其“消耗”并由实用程序代码解析为游戏机制的工作实例?

看来,我确实需要编写自己的语言和一个编译器))当然,我将无法做到。但是,也许有更简单的方法来解决这个问题?

仅供参考:我选择的实用程序语言是Python 3.x


由于您没有经验,只能作为一个开发人员工作,因此建议您不要尝试自己实现所有功能。使用SDL2库在许多方面对您非常有帮助,它们具有Python绑定,因此您可以使用自己喜欢的语言进行工作。为了实现您的目标,应该非常非常非常仔细地进行体系结构设计,即使对于有经验的团队,我也希望至少进行一次完整的重写。而且,Python确实没有比其他任何一种语言更容易学习,而且我认为在中级水平上存在很多陷阱。
ttbek

您正在寻找的概念在游戏开发人员之外很常见。有很多称为业务规则引擎的软件工具可以完全做到这一点。在游戏开发人员中,您还可以利用这些工具。例如,Apple的GameplayKit包含了GKRuleSystem和GKRule类,用于类似目的。进行扩展以允许对其进行外部编辑需要花费一些精力,但是可以通过某种方式来构造行为,而无需重新编译代码。
桑迪·查普曼

Answers:


34

一般而言,可扩展任何系统的难易程度取决于其子系统紧密或松散耦合的程度。通常,子系统之间的耦合越松散,修改它们就越容易,因为它们是隔离的,并且不一定需要对整个系统有完整的了解。

但是,没有什么是免费的-这样的系统通常需要更多的资源(时间,金钱和技能的各种组合)来构建。您所描述的可扩展程度使我感到惊讶,因为它与您赋予自己的技能水平直接相矛盾。可以做到,但是您所描述的制作软件是一项非常具有挑战性的工作。

我所知道的最接近的现有事物是Vassal(它比您描述的要编程得多),或为Tabletop Simulator制作一个mod(这主要取决于人类的交互来解释和执行任何游戏规则)。


可靠的建议。我尝试使我的代码尽可能松散地耦合以简化可扩展性,但是您总会遇到硬编码/耦合某些东西的情况。即使作为专业开发人员也不是一件容易的事,而且绝对不是新手友好的。
angarg12

TTS现在支持Lua,并且强制规则现在还不完全取决于人机交互。
大街

17

我想到的是,是否有可能/可行地以某种方式与主要实用程序代码分开实施游戏机制?

绝对有可能。游戏中经常使用的一种方法是Lua脚本

从链接的文章中:

Lua最初于1993年被设计为一种语言,用于扩展软件应用程序,以满足当时对定制的不断增长的需求。

许多游戏都使用Lua。(我会链接,但是新用户的声誉限制了我的链接数。)

Lua脚本可以在运行时进行编译。这意味着它们可以(例如)是位于游戏“脚本”目录中的文本文件,可以由修改器轻松编辑。您的游戏会加载并运行它们。

我已经看到Lua脚本定义了游戏单位的属性。是TA Spring的一个随机示例。

但是您想“描述所有规则”。从理论上讲,这可能是可行的,因为Lua是一门完整的语言,但是麻烦在于您必须足够有先见之明,才能使核心游戏代码知道来寻找脚本来扩展其行为。

例如,您可能开发了一种纸牌游戏,该游戏知道在“脚本/纸牌”目录中寻找纸牌。这对于添加新卡或编辑现有卡非常有用。但是,如果您以后想要扩展游戏以在网格上包含缩影,则必须编辑核心代码-绝不多的Lua摆弄就可以让您独自一人。

请注意:我提出Lua是因为我知道它在游戏和用于定制的软件中都普遍使用。我并不是说这是唯一的解决方案,也不是满足发问者需求的最佳解决方案。


7
这个答案暗示Lua是使用这种方式的唯一脚本语言。游戏引擎中还可以嵌入许多其他脚本语言。一些引擎也按照自己的方式来实现自己的特定于域的脚本语言。我通常不建议这样做(因为建立语言是一项繁重的工作),但是应该提一下。
菲利普

3

方法是一个连续的过程,其中任何一种方法是否值得,都将取决于您要尝试做的事情。具体来说,您想为调节器提供多少控制?

在控制的最高端,您只需让调节器修改整个游戏的代码即可。到那时,您实际上将发布实用程序代码以及至少一个如何使用它的示例。调节器可以根据需要使用或多或少的代码。

一种提供较少控制的方法是以某种方式“冻结”您的实用程序代码(例如,通过预先编译),并且仅允许调整者填写特定的函数(回调),从而限制了他们可以执行的操作。根据您要执行的操作,此方法可以采用多种形式。一种常见的方法是将所有显示部分放在实用程序/主代码中,并将所有机制放在可调整部分中。或者,您可能希望将某些机制保留在“冻结”部分中,因为玩家不太可能希望更改它们,或者使其变得可更改太复杂了。

在连续体的低控制端,只允许调节器在固定范围内更改值。一个可以让您选择游戏中事物颜色的数据文件就是一个例子。但是,您可以使用这种方法,并且仍然可以提供很多自定义功能。可以定义函数的选择,并允许调整器组成它们以使用以前的方法创建回调,但不允许它们定义新的函数。或者,也许您跳过了合成部分,只提供了一个有限的选择。

所有这些方法的细节以及哪种方法适合您的用例,取决于您要制作哪种基本游戏以及要放弃多少控制权。请注意,商业游戏通常仅使用第二种和第三种方法,因为第一种方法允许玩家制作完全独立的游戏,这会带来复杂的许可问题。注意,由于这些方法形成一个连续体,因此第二种方法也可能会引入这些问题。


实际上,使其成为开源是我的目标。我看到的一个问题是如何以最简单的方式实现这种可扩展性,以便游戏的其他玩家(MP游戏,顺便说一句)可以创建自己的基本规则扩展,并与每个规则共享其他,以某种方式同时避免冲突。因此,如果一个用户开发了覆盖某些规则的扩展,而另一个用户开发了不同的扩展,那么如何确保要在游戏中同时使用这两个功能的第三位用户不会遇到兼容性问题?除了强迫他们紧密合作。
那朵

..并以不需要修改任何实用程序代码的方式来实现它,因此不需要太多的编程知识。
那朵

1
我认为没有办法防止兼容性问题,(即使设置某种颜色也会导致这种情况!)我认为最好的办法是有一种方法来检测可能的兼容性问题并为用户提供一种不错的方法回复。根据实用程序代码接口的设计以及所涉及的扩展,可能有一种方法可以订购产生所需结果的回调等。再说一次,可能没有。提醒用户可能存在问题,为什么比没有任何解释的事情要好,这似乎是更好的用户体验。
Ryan1729

2

绝对有可能将系统规则与应用这些规则的代码分开。我更喜欢以这种方式为复杂的项目构建代码,因为这样可以更轻松地添加新规则或以后更改规则,而不会在基础系统中引入错误。与规则和其他代码杂乱无章地混合在一起的系统中的错误相比,规则引擎中的错误被发现得更快,因为每个规则都反复使用相同的规则引擎。

是否值得取决于系统的复杂性。就像我不会为吃豆人打扰一样,但我无法想象以其他方式编写《矮人要塞》。


谢谢,@ Robyn。对不知道如何正确进行此设计的人有什么阅读建议吗?是否有一些针对此类应用的完善设计模式?有涉及该主题的书籍吗?
那朵

没有书,对不起。但是,简单规则引擎的基本思想是:创建一个Rule类,该类具有描述规则所需的每条信息的属性。如果其中某些属性包含lambda函数,则可以为其分配复杂的行为。创建一个实例化“规则”列表的类,以便将所有规则放在一个位置。制作另一个类,该类具有一个将“规则”列表作为输入并将其应用到系统的方法。
罗宾

2

绝对可行。是否值得,取决于您的目标。

您无需发明自己的语言或编写编译器即可完成此工作。

如果您希望您的游戏易于扩展,那么这样做可能是个好主意。

至少短期内,为您创建更多易于理解的系统并使之易于修改的工作可能更多。

Rimworld(我没有从属关系)就是其中一种游戏,您也许可以查看和了解他们的工作方式,基本上将很多游戏数据和机制放入XML文件中,这些文件放在游戏文件夹中,任何人都可以查看和修改。游戏的核心/引擎是使用Unity制作的。

也有可能通过实际编码来进一步/深入地扩展游戏,对此我知之甚少,但您可以通过查看mods论坛来学习。

改装的可能性使游戏对很多人来说变得更加有趣,我认为它为游戏的成功做出了很大贡献。它还允许开发人员将他们想要的任何Mod内容引入到核心游戏中,并以某种方式加速开发并改进游戏,因为他们得到了很多人的帮助,并且他们可以基于受欢迎的东西,似乎有用的东西,等等。

当然,尤其是对于一个小型独立工作室而言,他们有数百人提出想法并对其进行测试,这是他们无法自己完成的许多工作,也可能无法雇用他们来做。


尽管我可以看到如何用xml定义游戏数据,但是我无法想象如何使用它来定义游戏机制/规则。您能否提供一些有关该主题的示例/文章?
那朵

@tis规则只是另一种数据。如果我的引擎有“ If A do B”,我可以从XML文件中加载A和B,那么用户可以放任意规则,另一点有用的方法是提供一个列表,其中包含您本身支持的所有可能的A和B ,例如“如果状态statustype则移动速度为100”,“如果状态statustype和时间> x则为状态statustype”,因此在设计中考虑要对哪些对象(状态,时间,移动速度)允许哪种规则,以及允许什么样的成分(和/或其他)。如果水下状态且时间> 5,则健康-10。
ttbek

1

您可能需要研究面向对象的设计。Python对此提供了良好的支持。

关于这方面的书籍很厚,新手可能会很害怕,但是主要原理很容易。

重点只是确定您正在使用的对象类型。您不会说自己正在考虑哪种游戏,但是诸如玩家,怪物,物品,装备,武器,护甲等都是典型的对象。

如果您想要不同的游戏类型,则可能需要兼顾胜利条件等的Game对象。也许还有Map对象?

有时不清楚某物是否值得成为物体,例如损坏。如果您不破坏对象,则代码会更简单,但是将其作为对象可以使自定义更容易。

类别武器和盔甲都是装备。设备是物品。可能还有其他类型的项目。您可能会发现定义玩家和怪物都是其子类的战斗员类别很有用。

这个想法是,例如,武器将具有与所有其他类型物品的许多共同点,它们具有重量,大小和类似的其他属性。

因此,子类化可以让您说“武器与其他物品一样,但是您可以使用它们,它们会影响您的伤害,等等”。

子类化还可以让您的mod生成器说“我的新型武器与标准武器一样,除了……”

然后,您必须确定哪个对象负责什么。这并不像看起来那么容易,您应该对此进行一些思考。做出错误的选择不会对基本游戏造成太大影响,但会使自定义变得更加困难。

只要您自己修补,就可以更改周围事物,但是当您向公众发布某些事物时,进行更改就变得更加困难!人们将根据像现在这样的事物来制作mod。甚至是错误。人们将编写依赖于代码中存在的错误的mod。如果您进行更改,则这些mod将会破坏,私刑小怪将出现在您的房屋中。

例如:

挥舞武器的玩家攻击穿着多副盔甲的怪物。这发生在特定的游戏模式和特定的地图上。

两个战斗者都可能具有暴击和闪避之类的技能。

现在,哪个对象负责什么?

没有一个正确的答案。在很大程度上取决于您要允许哪种定制。

如果您从不调用对象(例如地图),则该对象将无法以任何方式改变攻击。

在做出所有这些决定之后,将它们记录下来。编写“ Modders手册”,其中精确列出了每个对象具有哪些可修改方法,它们采用了哪些参数,应该返回什么等等,等等。

祝好运!


非常感谢您的投入,并且您付出了很多努力,因此它绝对值得+1,但总的来说,我碰巧知道OOP(尽管缺乏经验)。我当前的问题是我应该采用的大多数通用设计方法。我的游戏规模不如D&D大,但其机制仍然非常深入。这意味着很多复杂的,混杂在不同级别的规则。我想允许用户进行显着扩展,而不仅仅是稍微调整一些值。这可能是没有容易的解决方案,确实..
那朵

@tis关键是要对游戏的OO模型中的实际对象做出正确的决定。“显而易见”的起点不是唯一的方式,例如武器,盔甲等“名词”,它可能导致混乱的混乱代码。如果规则说“您只能在午夜在墓地里用银子弹射击一些怪物”,您将在代码中执行该规则吗?在“枪(或子弹)”类,“怪物”类,在“枪手”使用者的“战斗机”类,在“教堂墓地”类还是在“时间”类中?最好的答案可能是“以上
皆非

...并根据规则类(可能实际上是数据库)和冲突解决类重新考虑整个设计。现在,还有其他规则,例如“如果没有子弹,您仍然可以使用枪支作为棍棒”和“如果爱丽丝施放了部分(但不是全部)保护鲍勃免受子弹伤害的咒语,而查理试图射击鲍勃,然后....“将在代码中实现一个唯一且“明显”的位置。您可能会发现,原来的Gun类现在除了产生一些视听效果外几乎没有其他作用-如果是基于文本的游戏,则什至没有效果!
alephzero

1

获得一些基本支持的一种简单方法是将大多数数值分成一个或多个单独的文本文件,以使感兴趣的个人可以忽略它们。

例如,您提到桌上游戏;如果您有基于D&D的游戏,则可能会有一个weapon_damage文件,其中包含Battleaxe: 1d12。您的实用程序代码将读取该文件,并且只要Battleaxe您的代码处理了损坏,便会generate a number from 1-12, 1 time(s)添加该文件。调整行以进行读取Battleaxe: 4d6generate a number from 1-6, 4 time(s)然后添加它们。同样,Creatures对于每个生物,您可能都有一个文件夹,并且在内部有一个文件,包括类似AC: 12;的行。然后将新文件添加到该文件夹​​将创建新生物。甚至可以针对角色类,地形类型或大量事物来完成。

这种非代码自定义样式仍然非常强大,可以覆盖游戏的许多部分。但是,这实际上并不允许用户进行您未明确指定的更改。例如,您可以Sneak Attack: [damage]将其赋予任何生物或类,以添加[damage]到满足潜行攻击条件的任何攻击中。您甚至可以提供更改条件的方式,例如“每当隐身攻击时”,“每当侧翼时”或“每当有优势时”。但是,如果用户确定他们希望偷袭是“当您进行一次攻击掷骰时,您也可以根据目标的感知进行隐身攻击。如果两个掷骰都成功,则增加潜行攻击伤害”。

如果您希望用户能够在不需要与开发人员相同水平的编码技能的情况下向游戏中添加全新的行为,那么正如人们提到的那样,您正在寻找本质上是在创建游戏引擎还是使用单独的编程语言。对于不需要编码知识的修改,基于文本的数据文件和文件夹结构仍然可以提供很多选项。如果您想让用户进行更多的修改,则需要让他们学习或了解一种编程语言。


是的,我还需要允许他们添加新的机制,只是调整一些值是行不通的。我还认为这可能需要一种独立的语言,我只是想可能已经可以在我的Python实用程序代码中使用一种语言。
那朵

@tis您是否考虑过Wikipedia关于该主题的内容? en.wikipedia.org/wiki/Logic_programming
ttbek

0

[我是一个数十年的软件开发人员,但是没有游戏开发经验,所以也许游戏行业采用不同的方法,也许是有充分的理由...]

您的方法对我绝对有意义。该核心提供了机制和规则所基于的基本功能,因此它是供更高级别的组件使用的API。

在设计API时,我最喜欢的指导原则是创建您要表达高级代码的语言(当然,要受编程语言的语法限制)。

因此,一种好的方法是按照您希望的表达方式编写一些假设的规则和机制(当然使用Python的语法),从而找出您希望核心API提供给规则和机制的内容层。

当然,我建议您看一下现有游戏的脚本编制工具,以了解它们的功能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.