饑荒MOD lua編程0基礎入門

來源:互聯網
上載者:User

標籤:

前言

原貼寫於饑荒遊戲貼吧,為了使文章針對性更強,將原文切割並精簡。此貼主要為編程0基礎的modder講解一些編程的基礎知識。至於說有關饑荒架構的介紹,則會放在另一篇文章裡講解。

編程0基礎的人,要想學習製作MOD,難度是比較大的,因為缺乏一些基本的編程概念,只懂得複製別人的代碼或者在它們的基礎上稍加改變,遇到稍微複雜一點的代碼,就束手無策了。對於MOD崩潰或錯誤,也幾乎沒辦法自行處理。但我也不推薦先去學一門程式設計語言之後再來學習MOD代碼,這是沒有必要的。事實上饑荒MOD裡用到的基本編程知識都比較簡單,所使用的lua語言相比c之類的強型別語言,也已經做了許多簡化。單純想要做MOD的話,只需要瞭解一些基本知識和概念就可以了。

以下內容全部基於lua語言。

標識符

一個名字

給常量,變數,函數,類一個名字,這樣我們才能通過名字來使用它。一般使用英文字母、數字和底線的組合來命名。
推薦命名規則

  • 常量:每個字母都是大寫,在每個單詞之間加底線。
  • 變數和函數:第一個單詞首字母小寫,後續單詞的首字母大寫,其他都是小寫。
  • 類:所有單字首大寫。

這個只是個人推薦的命名規則,讀者可以根據自己的喜好決定命名規則。

變數

可以通過符號’=’賦值改變的量。

典型代表:人物的饑餓值。這個值在遊戲裡幾乎每時每刻都在不停變化著,這樣一來,我們就可以根據不同的變化,設定不同的效果,比如沃爾夫岡不同的饑餓值會有不同的形態,這個就是通過檢測饑餓值來實現的。

常量

程式運行時,不會被改變的量

實際上,lua語言裡沒法自己定義常量。但是,對於某些量,我們不需要在遊戲啟動並執行過程中改變,又需要引用它。比如說長矛攻擊力,在遊戲過程中不需要改變,但官方所做的所有的武器的攻擊力都是長矛攻擊力的某倍數,這又需要引用它進行計算。這時候,不妨就把長矛攻擊力看作是一個常量,用一個變數將其定義下來(SPEAR_DAMAGE,這個定義在tuning.lua裡)

範圍

變數的生效地區。

在範圍以外的域內,如果你引用這個變數,又沒有域內的同名變數,就會造成出錯。
lua中對一個變數的範圍只有兩個選項:local 和global。預設不加local修飾的變數為global(全域)變數,加了local的為局部變數。全域變數的範圍為整個程式。局部變數的範圍則在所定義的域中。一個選擇控制結構內,一個函數體內,或者一個檔案內,都是一個域。
這個範圍的主要價值在於,使得系統免於混亂。比如說,在被攻擊的時候,需要計算所受到的傷害,為了方便進行多次計算,我們把這個數值設定為一個變數。但是,面對的敵人的攻擊力會有變化,自身的防具減傷也會有變化,這時候我們就希望,計算結束,變數被引用到血量變化之後,這個變數能消失掉,不會影響我們下一次計算其他的傷害。這就是局部變數的重要作用。當然,局部變數還有另一個好處就是讀取它的資料,要比全域變數快一些,不過,提高MOD效能不是本篇教程的重點,就不詳細展開了。總而言之,全域變數,不到必不得已的情況,應當儘可能少用。

在上面我多次提到了聲明和引用,可能有些人不太清楚這兩個術語的意思。我這裡就順帶把定義和賦值一起講了。

定義和聲明

定義,就是告訴系統,我設定了的這個變數/常量是什麼。
聲明,就是告訴系統,我設定了一個變數/常量,你給我記好了。

定義和聲明是不一樣的,但常常會混在一起。如果你只是想寫寫mod的話,不瞭解他們的區別也沒關係,只認為是定義就夠了。

引用

引用就是告訴系統,我要用這個變數/常量來做某某事。

比如說用於某個運算式的計算,系統就會幫你讀取儲存在其中的資料。

賦值

賦值就是告訴系統,往這個變數/常量裡存入你給出的資料。

注意,此處的資料,不僅僅指數字,可以是lua語言允許的任何類型,比如說一段文字(字串),一個布爾值(真或假)等等。在某些語言比如C語言中,定義和賦值是可以分開的。但在饑荒MOD的指令碼語言lua中,這兩者是連在一起的。對一個變數的第一次賦值,就是對它的定義了。

資料類型

對變數賦值,就是給它寫入資料,那就涉及到了資料類型的問題。在初次賦值給一個變數時,所給予的值的資料類型,就是變數的資料類型。此後再給這個變數賦值,就必須賦予同一資料類型的值,如果值不同,就會導致系統崩潰(除了nil)。這裡不展開細講,只針對lua語言,簡單地列出MOD中常用的幾種類型

  • nil:表示無效值,可以給任何資料類型的變數賦這個值。實際效果相當於刪除這個變數
  • boolean:包含兩個值:false和true(假和真)
  • string:字串,用一對雙引號或單引號括起來
  • function:函數,這個會在下面講
  • table:表,這個概念會在後面講
函數

這是編程裡的一個非常重要的概念。

函數與變數的區別,可以做這樣的類比:一個變數,就好比是一個屬性,你可以給一個客體以某個屬性,讓它可以被描述,比如說,屬性:可以被燒毀。而函數,則是一種操作方法,你讓一個客體擁有一個函數,就是讓它有某種操作。比如說,操作方法:被燒毀的具體步驟和操作。

函數由函數名,參數表和函數體組成。函數也和變數一樣,能被引用,也有範圍。不過與變數不同的是,函數需要單獨定義,在不同的程式設計語言中,函數的定義格式不一樣,但都少不了上面所說的三個基本組成。在lua中,函數也可以看成是變數,可以被賦值。另外,函數可以有傳回值,也就是把計算的結果返回,供另一個函數或者運算式使用。

Lua中,函數定義的基本格式如下為:

function 函數名(參數表)函數體end

如果希望函數的範圍是局部的,則在function 前面添加local。這樣,你將無法在其範圍之外調用該函數。
函數是怎樣工作的呢?首先,你需要明白,定義函數並不會讓函數工作。只有執行了函數語句才會讓它工作。還是拿計算傷害來做例子。你定義了怎麼計算傷害的函數,參數為攻擊者的攻擊力和防禦者的護甲。這個函數在定義之後,本身並不會立刻工作。只有你設定了一系列的流程,讓函數在出現攻擊狀態的時候觸發,才能算是執行了這個函數。函數執行的時候,輸入了兩個參數:攻擊者的攻擊力和防禦者的護甲。在函數體中,經過一系列的計算,得到了結果,利用return返回來,由變數接收或者加在各種運算式裡使用。需要注意的是,即使是沒有參數的函數,在執行時,也必須寫成這樣的形式: 函數名(實際參數表)

代碼例子:

--定義了函數caldamage,但沒有執行function caldamage(attack,armor)        return attack-armorendlocal damage = caldamage(10,8) --這裡執行了函數caldamage,並把計算的結果返回,賦值給damage

函數的作用是什麼呢?就是使得你的編程顯得更有邏輯,模組化,還能減少代碼的使用量。定義好一個函數之後,就不再需要管這個函數裡面詳細的執行過程(也就是函數體寫了什麼),我們只需要知道這個函數的名字,參數表和傳回值,和這個函數有什麼作用。因為在饑荒的MOD中,大量的函數是沒有傳回值的(也就是傳回值為nil),執行這樣的函數,目的在於使用它的功能。
函數是做饑荒MOD時最重要的東西。我們做MOD,主要的目標就是修改或者向遊戲添加函數。瞭解這些函數在什麼時候會觸發,需要哪些參數,有什麼功能,傳回值是什麼,是非常重要的。

我們是在原遊戲的基礎上做MOD,也就是說,有很多已經定義好了的函數可以供我們使用。打個比方,饑荒這個遊戲,就好比一部車,函數就是這部車上面的零件,它讓這部車能夠擁有某些功能:啟動,刹車等等。我們現在覺得這部車不能滿足我們的需要了,那麼,很顯然的,做適當的改裝,要比重新造一部車容易。做MOD,就好比是做一些改裝。既然是改裝,那你就有必要瞭解到,你所需要改裝的部分,需要哪些零件。有些核心零件是非要弄清楚不可的。

現在饑荒MOD本身的結構是非常開放的,但官方沒有給出詳細的說明文檔,當我們想要實現一項功能的時候,我們不知道官方有沒有給出來,怎麼辦呢?我的建議是,思考一下遊戲裡的各種功能,以及他人已經發布的MOD,有沒有和你的需求類似的,去參考一下相應的代碼。易寧修改也是一個很好的參考,但易寧修改畢竟是直接修改遊戲的核心檔案,與MOD還是有一些區別的,所以要使用的話,前提是理解其含義。

表不是一門程式設計語言的必須概念,但這個概念在饑荒MOD裡使用得非常頻繁。遊戲的整個架構,也非常依賴於表。表的重要作用也和函數一樣,是為了讓你的編程顯得邏輯清晰。比方說,現在有4個個體,a,b,c,d,有多項屬性描述:health、sanity、hunger、damage、armor、attack_period、walkspeed、runspeed。這些屬性,對於4個個體來說,有的有,有的沒有,我們要怎麼組織起來呢?用多張表連起來,就是一個好主意。首先,我們來給屬性分一下類,health、sanity、hunger是饑荒中的三大基本屬性,各自單獨成一類,damage、armor、attack_period是和戰鬥有關的,分類為combat,至於walkspeed、runspeed則是和移動有關的,分類為locomotor。那麼,我們就有多張表了:

一張總表:

個體屬性工作表

屬性 a b c d
health a的血 b的血 c的血 d的血
sanity a的精神 b的精神 c的精神 d的精神
hunger a的饑餓 b的饑餓 c的饑餓 d的饑餓
combat a的戰鬥屬性 b的戰鬥屬性 c的戰鬥屬性 d的戰鬥屬性
locomotor a的移動屬性 b的移動屬性 c的移動屬性 d的移動屬性


這個表中的每一個元素,都是一張表,現在不妨取a的戰鬥屬性工作表出來,是這樣的:

個體屬性工作表

damage armor attack_period
數值 20 50 3



那麼,我們想要引用a1的damage的時候,怎麼辦呢?先在總表第一橫欄中找到a,然後在豎欄中找到combat,這樣我們就得到了提示:轉去找a1的戰鬥屬性工作表。然後在戰鬥屬性工作表中,我們在橫欄中找到了damage,這時候豎欄中只有一項,就不必再尋找了。我們在尋找過程中,尋找的a,combat,damage 就是所謂的索引。我們按先橫後豎的順序尋找的,a為1級索引,combat為2級,damage為3級。按順序最後找到damage的具體的值(20),就是所謂的值。這個值不僅僅是數值,比如說在總表中找到的a的戰鬥屬性工作表,也可以稱為值。再拓展一些,如果說戰鬥屬性工作表中的豎表不只有一項,而是有兩項:max,min,此時我們想要查damage最大值,該如何呢?那就要增加一個四級索引max。當你想要引用a的傷害最大值時,在編程裡的調用語句,你就可以寫a.combat.damage.max

結合饑荒Mod編程,我們常常會看到類似這樣的一條語句

inst.components.sanity:DoDelta(-10)`

這句話的意思是當前對象的精神減10。
具體是怎麼操作的呢?首先,遊戲裡這麼多個體,要在茫茫人海中找到你,必須要有個名字,這個名字就是inst,然後,inst下有很多屬性類,我們需要的精神值,歸類為components,也就是組件。組件這個概念,是饑荒為了編程上的邏輯清晰而創造出來的一個概念,會在介紹饑荒編程架構的文章裡詳細說明。然後我們繼續在components表裡找包含著精神值和操作精神值的函數的表,就是sanity。這時候你可以看到sanity後面是冒號:而不是之前的那些點號. 這是因為,我們是希望執行這個函數。如果是想要引用這個函數做其他動作的話,還是要用點號. 的。學過C++的人都會瞭解類的概念,對這個肯定不陌生。沒學過的人呢,看我在下面關於類的解釋。

類和物件導向編程

類這個概念,就是在物件導向編程的思想上發展起來的。為什麼要使用類呢?就是因為物件導向編程顯得邏輯結構清晰,易於實現、互動和維護。那麼,什麼是一個類呢?在編程上,可以理解為一些變數和函數的集合。這個集合是封裝起來的,其中有一些變數和函數你可以訪問和引用,稱為公有變數和公有函數,還有一些是你訪問不到,也無法使用的,就是私人變數和私人函數。需要注意的是,類本身只是一個邏輯結構,並不是實體。用現實的東西舉個例子,單車就是一個類的概念,它有很多基本屬性:顏色,材質等等,也有很多操作:騎、前進、刹車等等。屬性就是變數,操作就是函數。顏色、材質,是你能夠看到的,就是公有變數,而內部的轉盤的顏色你看不到,就是私人變數。而騎和刹車的操作,是你能夠決定的,就是公有函數。而前進這個操作,你沒法直接進行,你必須要反覆踩踏板,才能讓單車前進,所以前進就是私人函數。在頭腦中想到單車這個概念,就是類。而想到你的單車,就是一個具體的實體。

結合到饑荒MOD裡,sanity這就是一個類,這裡面有很多屬性:當前精神值,最大精神值等等,也有很多操作:精神增加/減少,設定當前精神值,設定最大精神值等等。而具體到一個人物的sanity,那就是這個類的實體了。
實際上,在lua裡,只有表,沒有類這個概念。但是饑荒的遊戲製作者為了編程方便,還是用某種手段,在表的基礎上,類這個概念創造出來了。我們只需要認識到,怎樣使用一個類就可以了。
引用類中的變數,操作方法就和參考資料表中元素一樣。如果想要調用函數,則需要將點號.改成冒號:,並且在函數名後面添加(函數參數表)。
比如說人物的當前精神值,人物的最大精神值等等,同時也有一些操作函數,比如上面舉例的DoDelta。我之前說過了,在lua裡,函數也可以看成變數。如果你想要引用這個函數,比如說引用去給一個函數賦值,那麼,上面的冒號:就要改成點號.,而且後面的”(-10)”也要去掉。如果你想要執行這個函數,那就要用冒號: 並且添加相應的參數。

以上就是全部的0基礎入門內容了。
理解了這部分內容,就可以去看下一篇,饑荒MOD架構概述了。

饑荒MOD lua編程0基礎入門

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.