跳转到内容

Celestia/Celx 脚本/简单 CELX 脚本

来自 Wikibooks,为开放世界提供开放书籍

继续阅读以了解简单的 CELX 脚本...

如果您有任何意见或问题,请将其发布到 Celx 问答 页面。

这是一个关于简单 CELX 脚本的教程。它基于“最好的学习方式是通过示例”的理念,因此包含了许多示例。每个示例通常都比前一个示例稍微复杂一些,但理解它可能取决于任何之前的示例,因此请确保在继续下一个示例之前完全理解每个示例。

要开始,您应该创建一个脚本文件用于测试目的。您可以将其命名为“test.celx”或类似名称。确保它具有“.celx”文件类型后缀,以便将其识别为 Celestia CELX 脚本文件。然后,您应该能够双击文件图标以使 Celestia 运行脚本。这比从 Celestia 菜单运行脚本要快得多。您可以同时运行 Celestia 和文本编辑器;当您准备好测试脚本时,只需保存更改并双击文件图标即可。Celestia 窗口应该弹出到最前面并运行您的脚本。观察结果后,您可以返回到编辑器窗口以对脚本进行进一步更改。并且不要忽视您可以直接从教程示例中剪切和粘贴代码这一事实!

简单开始

[编辑 | 编辑源代码]

这是一个简单的 CELX 脚本

celestia:flash("Hello, Universe!")
wait(2.0)

运行此脚本时,消息“Hello, Universe!”将在 Celestia 窗口的左下角短暂显示。这里的脚本指令非常简单。首先,我们要求名为“celestia”的对象执行其名为“flash”的函数以显示消息“Hello, Universe!”。然后,我们要求脚本等待 2 秒(以便我们有时间看到消息)。

我们对名为“celestia”的对象执行其名为“flash”的函数的请求格式是 Lua 的基本格式。首先,我们写下了对象的名称,在本例中为“celestia”。然后,我们写了一个冒号(:)来表示我们请求对象执行一个函数。然后,我们写下了我们要让对象执行的函数的名称,在本例中为“flash”。最后,我们写下了函数的参数,在本例中是字符串“Hello, Universe!”,用括号括起来。(请注意,我们没有在对象或函数的名称周围使用引号,只在参数周围使用引号。)其他对对象执行函数的请求具有类似的格式。

这是另一个示例

celestia:flash("Hello, Universe!")
wait(2.0)
celestia:flash("Goodbye, Universe!")
wait(2.0)

在这个示例中,我们对名为“celestia”的对象发出了两个请求。这两个请求都要求对象执行同一个函数(名为“flash”),但我们在每个请求中为函数指定了不同的消息字符串作为参数,导致对象在每个请求中以不同的方式评估函数,从而显示不同的消息。

一个简单函数

[编辑 | 编辑源代码]

现在让我们编写自己的函数

 function flash(message)
  celestia:flash(message)
  wait(2.0)
 end
 
 flash("Hello, Universe!")
 flash("Goodbye, Universe!")

在这个示例中,我们定义了自己的“flash”函数,以包含 2 秒的等待。然后,我们要求脚本执行我们的新函数两次,每次使用不同的字符串。

我们的新函数名为“flash”,但它与名为“celestia”的对象所属的同名函数不同。相反,新的函数属于我们的脚本。当我们要求脚本执行我们的“flash”函数时,我们不需要写下对象或冒号(:)的名称。我们只需要写下函数的名称,后跟括号括起来的参数。

但请注意,当我们定义我们的新函数时,确实使用了对象名称和冒号,因为在那里我们确实希望要求名为“celestia”的对象执行其名为“flash”的函数。

函数定义的格式是另一个 Lua 基本格式。首先,我们写下关键字 function。然后,我们写下函数的名称,在本例中为“flash”。然后,我们写下参数的名称,用括号括起来。在本例中,参数名为“message”。然后,我们写下脚本将遵循的指令序列以执行该函数。最后,在函数的末尾,我们写下关键字 end。(请注意,我们没有在函数或其参数的名称周围使用引号。我们只需要对文字字符串使用引号,而不需要对名称使用引号。)

在本例中,执行我们函数所需的指令是要求名为“celestia”的对象执行其名为“flash”的函数,使用我们函数的参数名为“message”作为对象函数的参数。然后,我们要求脚本等待 2 秒。

请注意,我们首先定义了我们的函数,然后我们调用了它(两次)。(当我们说“调用”时,我们的意思是我们要求脚本执行函数。)当我们定义函数时,我们将其参数命名为“message”。我们在用于指定函数执行方式的指令中引用了该名称。然后,每次我们调用该函数时,我们都会指定一个特定的字符串作为“message”,脚本在执行该函数时会使用该字符串。

但是您也可以在函数调用中使用名称而不是实际字符串,例如以下示例

 function flash(message)
  celestia:flash(message)
  wait(2.0)
 end
 
 flash("Hello, Universe!")
 farewell = "Goodbye, Universe!"
 flash( farewell)

在这个示例中,我们首先将名称“farewell”赋予字符串“Goodbye, Universe!”。然后,我们要求脚本使用该名称而不是字符串本身执行我们的“flash”函数。我们将名称赋予字符串的指令语法是另一个 Lua 基本语法。它由名称(在本例中为“farewell”)组成,后跟一个等号 (=) 来表示我们正在将名称赋予后面的内容,然后是请求对象执行函数(并返回其结果)。

顺便说一下,函数定义还有另一种稍微不同的格式,我们将在下一个示例中使用。

 flash = function (message)
       celestia:flash(message)
       wait(2.0)
       end
 
 flash("Hello, Universe!")
 farewell = "Goodbye, Universe!"
 flash( farewell)

在我们在此示例中使用的格式中,函数的名称不会出现在 function 关键字之后。相反,它会首先出现,后跟一个等号 (=)。接下来是 function 关键字,后面直接跟着括号括起来的参数。然后是定义函数的指令序列,最后是 end 关键字。与我们之前定义函数的方式唯一的区别是函数名称的位置,以及添加了一个等号。

如果这种新的函数定义格式看起来非常像变量赋值,那并非巧合:它确实就是变量赋值。我们只是在给一个函数命名,就像我们在前一个示例中给一个字符串命名一样。我们将在后面回到这个事实的非常重要的含义。请注意,您使用哪种格式并不重要。它们的含义是相同的。

从现在开始,为了简洁起见,我们的示例将假设我们已经像前面的示例之一那样定义了 flash 函数。

更多示例

[编辑 | 编辑源代码]

现在让我们尝试使用名为“celestia”的对象提供的另一个函数

 time = celestia:gettime()
 flash(time)

在这个示例中,我们要求名为“celestia”的对象执行其名为“gettime”的函数,并将名称“time”赋予对象返回给我们的结果(一个数字)。然后,我们要求脚本执行我们的“flash”函数,使用名为“time”的数字作为“message”参数。

名为“celestia”的对象执行其名为“gettime”的函数不需要任何参数,因此函数名称后面的括号为空。

我们将名称赋予此函数请求的结果的指令语法是另一个 Lua 基本语法。它由名称(在本例中为“time”)组成,后跟一个等号 (=) 来表示我们正在将名称赋予后面的内容,然后是请求对象执行函数(并返回其结果)。

运行此脚本时,您会看到一个短暂显示的大数字。此数字是 Celestia 中的当前时间设置,以儒略日期表示。(它是自儒略历纪元开始以来的天数)。

在下一个示例中,我们将使这一点更加清晰

 time = celestia:gettime()
 timeMessage = "The current time is " .. time .. " (Julian date)."
 flash(timeMessage)

更多内容即将推出...

[编辑 | 编辑源代码]

警告:前方施工区域!自行承担风险!


在下一个示例中,我们将将其转换为更易于识别的形式

幸运的是,celestia 对象有一个函数可以帮助我们做到这一点

 jdate = celestia:gettime()
 flash(jdate)
 date = celestia:fromjulianday(jdate)
 flash(date.year)

在此示例中,我们要求 celestia 对象提供时间,然后要求它提供将儒略日期转换为日历日期的结果,最后要求脚本使用我们的“闪光函数”来显示表示年份的那部分日期。

要显示完整日期,我们需要将年份、月份和日期的日期部分连接起来

 jdate = celestia:gettime()
 flash(jdate)
 date = celestia:fromjulianday(jdate)
 dateString = date.year.."/"..date.month.."/"..date.day
 flash(dateString)

以下其他示例有待解释。同时,欢迎您自己尝试找出答案!

 saturn = celestia:find("Saturn") -- finds object named Saturn
 radius = saturn:radius() -- gets radius of Saturn
 flash("The radius of Saturn is "..radius.." km.")
 flashRadius = function (bodyName)
              body = celestia:find(bodyName) -- finds object 
              radius = body:radius() -- gets radius
              flash("The radius of " .. body:name() .. " is " .. radius .. " km.")
            end
    
 flashRadius("Jupiter")
 jupiter = "Jupiter"
 flashRadius(jupiter)
 reallyBigPlanet = "Jupiter"
 flashRadius(reallyBigPlanet)
 selectedPlanet = celestia:getselection() -- gets the planet currently selected by the user
 flashRadius(selectedPlanet:name())
 flashRadius = function (body)
             if type(body) == "string" then
               body = celestia:find(body) -- finds object 
             end
             radius = body:radius() -- gets radius
             flash("The radius of " .. body:name() .. " is " .. radius .. " km.")
            end
 selectedPlanet = celestia:getselection()
 flashRadius(selectedPlanet)

在此示例中,我们定义了一个函数来闪烁显示一条消息,报告指定行星的半径。然后我们调用了该函数两次,以显示两个不同行星的半径。这应该与您从以前示例中看到的一切都一样。(在未来的示例中,您应该假设我们的 flashRadius 函数已经定义。)在下一个示例中,我们将以稍微不同的方式执行相同操作

 planetList = { "Uranus", "Neptune" }
 flashRadius(planetList[1])
 flashRadius(planetList[2])
 planetList = { "Earth", "Moon", "Mars" }
 for index = 1,3 do
   flashRadius(planetList[index])
 end
 planetList = { "Earth", "Moon", "Mars", "Venus", "Mercury" }
 for index,name in ipairs(planetList) do
   flashRadius(name)
 end
 selectedObject = celestia:getselection()
 flashRadius(selectedObject:name())
 cassini = celestia:find("Cassini") -- finds object named Cassini
 saturn = celestia:find("Saturn") -- finds object named Saturn
 cassiniPosition = cassini:getposition() -- gets position of Cassini
 saturnPosition = saturn:getposition() -- gets position of Saturn
 distance = cassiniPosition:distanceto(saturnPosition) -- gets distance from position of Cassini to that of Saturn
 distance = distance-saturn:radius() -- adjusts for distance to surface
 flash("Current distance from Cassini to Saturn's surface is "..distance)

这个更有趣一些

 -- tour the moons of Saturn
 obs = celestia:getobserver()
 planet = celestia:find("Saturn")
 obs:goto(planet)
 wait(5)
 flash("Welcome to "..planet:name())
 moons = planet:getchildren()
 for index,body in ipairs(moons) do
   if body:type() == "moon" then
     obs:follow(body)
     obs:goto(body)
     wait(5)
     flash("Welcome to "..body:name())
     wait(1)
   end
  end
 -- tour the stars at random
 obs = celestia:getobserver() 
 stars = celestia:getstarcount() 
 for i = 1,stars do 
  j = math.random(stars) 
  obj = celestia:getstar(j) 
  obs:goto(obj,20) 
  while obs:travelling() do wait(0.5) end 
  celestia:flash("Welcome to "..obj:name(),2) 
 end



返回 Celestia/Celx_Scripting
返回 Celestia

华夏公益教科书