允许在游戏内部进行编程的技术是什么?


27

有一些游戏允许玩家在游戏中编写/创建脚本,例如:太空工程师Psi

我想使用与任何一个相似的东西,但是我很难找到信息,所以我的问题是:

是否有一个编程分支涵盖了软件一旦编译后即可运行用户创建的新代码的能力?

在编程方面,我的意思是类似PTG(过程地形生成)。

为避免基于问题观点的范围太广,请让我明确声明我不是在寻找指南或学习的地方,我想要所涉及技术的名称或定义(如果有的话)。


22
好吧,可能是“笔译”?
MatthewRock '16

2
我最近回答了一个类似的问题,讨论了“ 虚拟机 ”作为运行用户代码的系统的术语,并且还引用了字节码模式中的“ 游戏编程模式”文章,以比常规解释器更快地实现此目的。
DMGregory

3
通常称为“脚本”。您会发现很多有关如何在游戏中实现脚本的材料,以及大量(各种)开源示例和真实代码。在更广泛的范围内,存在编译器编程的整个领域(包括词法分析,解析,编译,链接,解释...)。在最广泛的范围内(不一定有用),这几乎包含了应用程序与用户的任何交互-脚本引擎实际上只是从菜单中进行选择的一种更为复杂的方法。
六安2013年

2
Python程序可以托管Python脚本。这就是所谓的元编程。大多数解释语言都具有这种功能。
user6245072 16/09/26

1
AFAIK是Space Engineers中的代码,代码是在沙盒环境中编译的C#代码(游戏为开源程序,因此您可以在线查看其工作方式:github.com/KeenSoftwareHouse/SpaceEngineers)。基本上,游戏附带C#编译器,并且代码仅允许访问游戏的API函数,因此该程序的范围仅限于您自己。而且,如果您正在玩多人游戏,那么代码只会在您的计算机上运行(其他玩家/服务器只会看到游戏中的后果)
Florian Castellane

Answers:


42

脚本/嵌入式/解释语言编写的脚本,例如“ Lua”,“ Lisp”或“ AngelScript”(此处有更多信息),可以在游戏[*]期间进行更新,然后即时进行解释(=执行)。

您可以将这些脚本中的元素绑定到您的本机编译代码(C ++等),以便脚本随后可以从您的应用程序中执行逻辑。例如 用户可以在脚本中输入的特定命令,从而将游戏中角色在游戏世界中移动给定距离。

一些相关的链接问题:


[*] 由用户作为游戏的一部分,也由开发人员用于快速迭代/测试,而无需重新启动应用程序


14
我称呼“解释性语言”时会很小心。充其量是一个非常有争议的术语。
温德拉

1
Computercraft(minecraft mod)使用LUA作为脚本语言对游戏中的任务进行编程。
Tikeb

20
我不太了解大惊小怪。Lisp可以被解释和编译。我们不是在这里讨论如何对语言进行分类以及是否interpreted具有良好的从属关系。我们告诉OP谁不知道这个事实,即语言不需要编译但可以解释-我们以某些语言为例。Lisp会被解释吗?是。它被编译了吗?还可以!但这超出了范围。答案可能与措辞不正确,但这样做是正确的。它将OP推向正确的方向,这才是最重要的。在这里,取我的+1。
MatthewRock '16

1
好吧,即使一种语言仅是编译语言,是什么阻止您将IDE,编译器和运行时嵌入到游戏中呢?除了预算,就是这样。
Ordous

3
@DanielJour虽然我会同意一种语言在理论上可以与实现不同(编译为机器代码或编译为vm的字节码),但除非另有说明,否则仍然是一个有用的节省时间的假设,即编译C如果您每次问“等待,编译C还是解释C?”,您将获得的外观)。出于OP的目的,他需要研究支持解释的语言。是否也可以编译它们不是问题,因为他不是那样使用它的。
Blackhawk

12

嵌入式语言是正确的技术术语。实际上,在其他应用程序(例如游戏)中使用的语言通常被称为脚本语言或什至是解释语言,尽管它们不一定必须被解释或用于自动执行例行任务。谷歌搜索“游戏脚本语言”可能会比搜索“嵌入式语言”产生更多有用的结果。


11

您正在寻找一种将代码更改为某些操作的方法。这正是口译员正在做的事情。

看一下Python。您运行它,ba!你土地REPL[R EAD é VAL P RINT 大号接力)。

您定义一个函数“ hello”,该函数显示“ Hello,world”。在那里,您拥有了!

请注意,您没有编译任何内容。解释器在运行时(运行时)做了一些魔术来动态创建函数,现在您可以调用它了。

游戏同样如此。您没有REPL,而是拥有带有REPL模块的游戏。游戏可能会启动REPL,然后运行该REPL中的其他所有内容,因此您可以访问数据并可以对其进行主动修改。

如果您使用的是C ++之类的大型语言,则它们的动态性可能会降低,并且可能会进行编译。您想要一些简单的方法。您可以创建自己的语言,也可以使用现有的语言(例如CoffeScript,Squirrel,Lua,Scheme等)

这些通常称为脚本语言,因为您使用它们来编写基于以其他某种语言(例如C ++)开发的游戏引擎构建的脚本


2

如果游戏内编程语言仅是为游戏目的而设计的,则它是领域特定的语言

特定于域的语言的优点(和缺点)是,语言本身会限制用户的操作(即您可以禁止连接到Internet)。您可以设计一种使通用游戏任务比通用语言更容易的语言。缺点是用户必须学习一种新的语言。

仅在您的游戏中以通用语言(例如python或perl)运行未经消毒的用户代码,就可能使用户惹上他不该惹的麻烦。但这取决于您的游戏。如果您不介意用户做诸如在游戏中或他们喜欢的任何事情中打开新窗口之类的事情,则可以使用通用语言并向游戏世界的某些功能公开绑定。


1

我可以想到两个例子。两者似乎完全符合您的要求。

首先是小腿。https://screeps.com/您可以在http://support.screeps.com/hc/en-us/articles/205960931-Server-side-architecture-overview中阅读有关其如何实现此目标的大量信息。

第二个是ComputerCraft http://www.computercraft.info/ 他们没有详细介绍它的工作方式,但是可以在他们的Wiki http://www.computercraft.info/wiki/Main_Page上看到一些细节

本质上,主游戏在单独的线程中运行解释器,然后允许该线程通过API调用来操纵游戏世界。

在这两个示例中,尽管语言几乎是无限的(出于安全原因仅阻止了某些调用),但是操作受到可以进行的API调用的限制。

通常,只需很少的工作就可以开始这样的事情。你需要

  • 保护游戏循环的线程管理器(不允许线程锁定循环或消耗大量资源)。这两个示例都使用基于时间的限制器。
  • 一位翻译来运行一种语言。如今,LUA非常普遍。
  • 一组修改游戏世界的API调用。如果您不能做任何事情,那么编程语言就是什么乐趣。
  • 资源管理实现。换句话说,一种存储代码文件并在游戏中引用它们的方法。

没有一个编程的分支可以处理所有这些问题。但是您将需要在多线程方面有坚实的基础,并且需要有关解释器工作原理的一般知识。


0

编译后的可执行文件必须包含一个能够读取外部程序代码解析器 。程序代码不必像C或Python或xyz一样-它可以是任何适合描述目的的描述性数据。例如瑞典语或莫尔斯语。

外部程序代码需要具有一种语法,以便解析器在逐个字符地读取它时可以理解它。语法可以描述(并且代码可以包含)标识符,数值,运算符等

解析器是固定的(已编译),但可用于灵活的外部代码。

编译后的可执行文件必须具有与其相关功能的内部API。以便解析器可以执行操作。很有可能还必须(双向)访问可执行文件的内部数据,否则解析器必须提供某种类型的数据存储和内务处理。

解析器可以在可执行文件的读取外部程序代码启动,或者它可以读取(部分)它特设,或者它可以重新读取每帧它(将是低效的),或所述代码甚至可以是手工类型和准备就绪时将其发布到解析器(例如:“将单元X向前移动5个步骤” [输入])。

本质上,外部代码不是固定的 -可以更改任何年份,日期或分钟,但是仍然无需重新编译可执行文件。仅可执行文件托管的结果行为会更改。

您当前正在阅读的文本(种类很多,甚至可以说出来)被解释是因为您在阅读时在大脑中“执行”了该文本,却不知道下一句话说的是什么(或者即使可能,也偷偷地改变了)现在)。与Stack Overflow(堆栈)将整个故事预编译为大脑中的字节码相反,然后执行该故事-然后,ofc再也无法更改了。

正在进行现象是解释。脚本编写只是创建说明或编写代码的行为。所有的计算机编码都是imo脚本-我们描述了我们想要发生的事情。“脚本”一词的含义有些偏斜,但是可以了。我们知道我们的意思。

解释语言绝对没有什么特别之处,绝不是可争议的术语。它们存在很多,并且一些最古老的被解释为与已编译相反。例如,可以使用一种解释性语言手动键入:

袜子= Socket.New(AddressFamily.InterNetwork,SocketType.Stream ProtocolType.Tcp)[ENTER]

...然后进行30 ...不,45分钟的茶歇:-)。返回时,存在“袜子”,可以通过手动键入更多内容或让解释器的自动化继续进行来准备进一步使用。


常见的误解是解释的语言必须很慢。这不是真的。取决于使讨论过于广泛以至于无法进行评论的各种因素,解释语言的速度可能比控制语言(通常为C)快一个数量级或更小,甚至更快,甚至某些操作更快。带有socket的示例可能或多或少地类似于C语言,因此该示例具有误导性。您还可以在运行时以某些语言重新定义已编译的函数,并且解释不仅仅意味着“一次执行一条指令”。
MatthewRock

当然,一种解释语言也可能执行得更快-毕竟它是字节码才能执行,而且执行可能会更好地优化,具体取决于解释器的自动化程度。另外,某些解释器可以将代码的部分代码编译为字节码(并执行),该示例是自由的示例,“一次执行一条指令”吗?嗯,这是一个过分的简化,也许添加“将来的代码是灵活的”。
暴风城

将“剧本”想像成电影剧本,您仍然需要演员,而这些演员是直接根据生物学和社会学而不是戏剧科学来定义的(尽管它们最终基于生物学和社会学),因为这些语言更多适用于该目的,但不适合其他目的:)
rackandboneman
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.