Celestia/Celx 脚本/简单 CELX 脚本
继续阅读以了解简单的 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