跳转到内容

Celestia/Celx 脚本编写/开发建议

来自维基教科书,开放世界中的开放书籍

一旦您超越了编写最简单的 CELX "Hello World" 脚本,软件的开发就会成为一个问题。Lua 编程与任何其他语言的编程一样复杂,甚至可能比许多语言更具挑战性。由于 Lua 是一种解释型语言,具有运行时编译器,因此查找细微错误通常是一个问题。以下是一些建议,有助于更轻松地开发和调试 Celestia 的 Lua 模块。

Celestia 在许多方面都是一个了不起的应用程序,其中最不重要的是它以 Lua 的形式提供了可扩展性,Lua 是它的内置编程语言。Lua 速度快、功能强大,可以增强 Celestia 体验,其方式仅受想象力的限制。但正如本叔叔曾经对彼得·帕克说过的,能力越大,责任越大。Celestia 的 Lua 不会牵着你的手。它几乎病态地坚持让你几乎可以做任何事而不会抱怨。就像有一个女朋友,她太甜了,从不抱怨任何事。然后有一天她不见了,你发现了一张关于你从不收拾袜子的恶毒便条。Celestia 的 Lua 就是这样。你可以几乎做任何事,但代价很高。而且 Lua 甚至不会留下便条。有一天 Lua 会抛弃你,你根本不知道为什么。但这不像 Lua 不会告诉你她的问题,如果你问的话。你只需要问。(对你女朋友来说也是个好主意。)

您需要做的第一件事是熟悉一个名为 "pcall" 的 Lua 函数,就像 Lua 的所有函数一样,您可以在 "Lua 参考手册" 中找到完整的描述,该手册以书籍或在线形式提供,可在 https://lua.ac.cn/manual/5.0/ 获取。

您应该编写的第一个函数之一类似于

 error_pause = 20
 
 result, error = pcall( f )
 if(result == false) then
 	celestia:print(error, error_pause)
 	wait(error_pause)
 end

其中 "f" 是您编写的函数。当您开始编程时,您应该养成使用 pcall 调用所有函数的习惯。当您的程序调试完毕后,可以根据需要删除它们,但您可能应该保留包含 pcall 语句的程序副本。很有可能,您可能希望修改您的宝贝。

您实际上是在复制大多数其他语言内置的错误报告。这里的优势在于,当您完成操作时,可以消除错误检测的开销。

接下来您应该做的事情(如果您还没有做的话)是阅读 Harald Schmidt 关于 Lua/CELX 脚本编写的在线描述,网址为 http://celestia.h-schmidt.net/celx-summary-latest.html 这将提供所有可用的 Celestia 功能,以及一些关于 Lua 的提示,但我建议您还阅读 Lua 手册,并结合 Harold 的描述进行阅读。

编程风格

[编辑 | 编辑源代码]

可扩展程序

[编辑 | 编辑源代码]

当然,编程风格是见仁见智的,但如果您要编写任何大型程序,我建议您利用 Lua 的能力,在需要时简单地读取新代码。例如,下面的 dofile 就是一个示例。

 function dofile(filename)
 	s = assert(loadfile( filename ), "unable to load " .. filename)
 	return s
 end

此函数将编译文件中的代码,并在失败时发出错误。

在这种情况下,您可以利用 Lua 的垃圾收集器。Lua 定期对程序不再链接的任何内存进行垃圾收集。"dofile" 上面的代码可能会覆盖链接,Lua 会自动(最终)释放内存,如果您需要,您的代码几乎可以无限扩展。这也适用于您可能读取的任何文本。覆盖对字符串的链接会释放旧内存。

简洁至上

[编辑 | 编辑源代码]

Lua 遵循 KISS 原则:"保持简单,愚蠢。"Lua 中只有八种数据类型:nil、布尔型、数字型、字符串型、函数型、userdata、线程型和表型,其中 "userdata" 只是一个未定义的内存块。

相信我,简洁是一件好事,仅仅因为它比记住更容易设计。您可能最常使用的数据类型是表,它实际上是一个数组,几乎可以用任何东西(除了 nil)作为索引。

Macintosh 提示

[编辑 | 编辑源代码]

如果您在 Mac 上编程,请注意,Mac 版本与 PC 版本有一些细微的差别,其中最主要的是如何处理注释。手册中说注释可以以 "[[" 开头,但这在 Mac 上不起作用。我在 Mac 上使用的注释形式是

--[[ this is a comment ]]

请注意,"--" 位于括号之前。对于多行注释,我使用

--[[

      The following code is the most magnificent piece of ...

--]]

注意:这似乎是由 Mac 文本编辑器充当文字处理程序造成的。它们假设当您键入两个连字符后跟一个空格时,您实际上想要一个 em 连字符(一个单一的、双宽连字符),并用双宽连字符的单个二进制代码替换这两个连字符。不幸的是,这破坏了 Lua 的注释约定,该约定需要两个单独的连字符字符。幸运的是,如果您在两个连字符后跟任何字符(空格或制表符除外),Mac 编辑器就不会进行替换。

崩溃 Celestia

[编辑 | 编辑源代码]

无限递归

[编辑 | 编辑源代码]

Celestia v1.5.0 无法检测到 ScriptedOrbit 或 ScriptedRotation 何时为将具有其位置或方向作为 ScriptedOrbit 或 ScriptedRotation 的副作用而修改的对象调用 obj:getposition() 或 obj:getorientation()。

因此,如果 "obj" 的位置(或方向)由该 Scripted 函数决定,即使是间接决定,也不能从 Scripted 函数中调用 obj:getposition()(或 obj:getorientation())。这样做会导致 getposition() 调用例程,这些例程会调用 Scripted 函数,该函数又会调用 getposition()... 无穷无尽。这会很快耗尽堆栈空间并导致 Celestia 崩溃。

建议:Scripted 代码可以简单地返回之前的位置或方向,而不是尝试计算新的位置或方向。

希望这种情况会在 Celestia 的未来主要版本中得到解决。

在 celx 脚本中需要一个 lua 文件

[编辑 | 编辑源代码]

在 celx 脚本中使用 Lua 的 'require' 函数时,Lua 会使用 Celestia 的根目录来查找 Lua 文件。 然后,您可以在 celx 脚本中定义不同的路径,使用

 package.path = "mypath/?.lua;"

要将 celx 脚本的目录设置为默认路径,只需在脚本开头添加以下行:

 package.path = celestia:getscriptpath().."/../?.lua;"
华夏公益教科书