跳轉到內容

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

華夏公益教科書