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