圖形用戶界面編程入門

本文介紹Don't Starve 圖形用戶界面(Graphical User Interface,簡稱GUI)編程的基本概念,并給出簡單的操作實例。

實例下載

基本概念

在Don't Starve中,圖形界面的核心由兩個大類組成:WidgetScreen。Widget是用于界面上的小組件的,比如說一個物品欄,物品欄上的一個單元,都是一個簡單的widget。Screen則是一整個界面,比如說選項界面,小地圖界面等等。一個Screen里可以包含多個widget,一個widget也可以內(nèi)含許多widget。在游戲中,widget和screen并沒有明確的分界線,這里說的概念也僅僅是一種邏輯上的區(qū)分而已。由于在GUI編程中,Widget是Screen開發(fā)的基礎(chǔ),而且實際開發(fā)中使用的頻率遠(yuǎn)遠(yuǎn)高于Screen,所以這里主要講解Widget,而把Screen作為拓展內(nèi)容。

Widget和Screen都只是一個基本類,要實現(xiàn)諸如按鈕,文字輸入等功能,則需要進(jìn)行擴展,也就是繼承Widget或Screen類,在此基礎(chǔ)上更進(jìn)一步增加新的東西。官方已經(jīng)做好了一些常用功能的擴展,包括按鈕,文字,圖片,動畫等等。在聯(lián)機版里,為了進(jìn)一步節(jié)約開發(fā)時間,官方還做了一些常用模板。這些模板是為固定情景而設(shè)計好的完整的Widget,可以簡單地通過一兩句代碼調(diào)用,而無需再自行編寫復(fù)雜的Widget。

Child

在圖形編程中,常常會用到一個函數(shù)AddChild。這個函數(shù)會將傳遞進(jìn)來的對象設(shè)置成執(zhí)行這個函數(shù)的對象(我們稱為Parent)的一個Child。從而在Parent執(zhí)行一些操作時,會讓Child同步執(zhí)行。
比如說,當(dāng)Parent的坐標(biāo)變化時,Child的坐標(biāo)也會跟著變化。再比如說,Child的原點會被設(shè)置成Parent的坐標(biāo),從而使得Child的坐標(biāo)變成相對坐標(biāo),在調(diào)整時無需關(guān)心Child的屏幕坐標(biāo),只需要關(guān)心它相對于Parent的位置偏移就行了。這就使得Parent和Child變成一個緊密相連的整體,大大簡化了相關(guān)的操作。

Hello Widget

大多數(shù)編程的學(xué)習(xí),都是從最簡單的Hello World開始,我們這里就從編寫一個可以在游戲內(nèi)頂部居中顯示"Hello Klei"的Widget開始。
這需要做兩件事:

  1. 編寫一個Widget
  2. 把這個Widget加載到游戲里去

創(chuàng)建Widget

創(chuàng)建Widget是十分容易的,你只需要為你的widget想一個名字,比如Hello,然后在mod根目錄/scripts/widgets文件夾下創(chuàng)建一個lua文件hello.lua。然后寫一個類,繼承Widget類或它的一個子類即可。
一般來說,推薦直接繼承Widget,對于想要使用的特別功能,使用組合的方式來實現(xiàn)。這是因為,在MOD制作者編寫的Widget通常是復(fù)合型的,比如可能同時含有按鈕和文本,這時候,無論是繼承Button類還是Text類,在邏輯上都是不合適的。正確的做法是,繼承Widget類,再在成員變量里按需要添加Button和Text。

首先,創(chuàng)建一個mod項目,然后在mod根目錄/scripts/widgets文件夾下創(chuàng)建一個lua文件hello.lua,然后,編寫代碼如下:

-- 首先,在文件的頭部寫上需要加載的Widget類
local Widget = require "widgets/widget" --Widget,所有widget的祖先類
local Text = require "widgets/text" --Text類,文本處理

local Hello = Class(Widget, function(self) -- 這里定義了一個Class,第一個參數(shù)是父類,第二個參數(shù)是構(gòu)造函數(shù),函數(shù)的參數(shù)第一個固定為self,后面的參數(shù)可以不寫,也可以自定義。
    Widget._ctor(self, "Hello") --這一句必須寫在構(gòu)造函數(shù)的第一行,否則會報錯。
    --這表明調(diào)用父類的構(gòu)造函數(shù)(此處是Widget,如果繼承Text,則應(yīng)該寫Text._ctor),第一個參數(shù)是固定的self,后面的參數(shù)同這個父類的構(gòu)造函數(shù)的參數(shù),此處寫的是Widget的名字。
    --
    self.text = self:AddChild(Text(BODYTEXTFONT, 30,"Hello Klei")) --添加一個文本變量,接收Text實例。
end)

return Hello

如此就完成了Hello Widget的編寫。

加載Widget

Widget實質(zhì)上是一個小部件,它需要依附于screen才能使用。游戲里通過FrontEnd來調(diào)度不同的screen,從而顯示出不同的Widget供玩家查看和操作。
不過,一般來說,用于MOD的widget,多數(shù)不需要直接依附于screen,而只需要依附于screen下的一個widget就行了。
以最常見的,為游戲中的操作界面添加widget為例,screen是HUD,但我們不需要讓自己編寫的widget直接依附在HUD上,只需要依附在controls這個widget上就行了。controls是一個大型的綜合性widget,玩家操作界面的物品欄,制作欄,狀態(tài)欄等等,都是由這個widget統(tǒng)一進(jìn)行管理的。

下面就來把Hello Widget添加到這個controls里。

在modmain.lua里添加如下內(nèi)容:

local hello = GLOBAL.require("widgets/hello") --加載hello類
local function addHelloWidget(self)
    self.hello = self:AddChild(hello())-- 為controls添加hello widget。
    self.hello:SetHAnchor(0) -- 設(shè)置原點x坐標(biāo)位置,0、1、2分別對應(yīng)屏幕中、左、右
    self.hello:SetVAnchor(1) -- 設(shè)置原點y坐標(biāo)位置,0、1、2分別對應(yīng)屏幕中、上、下
    self.hello:SetPosition(70,-50,0) -- 設(shè)置hello widget相對原點的偏移量,70,-50表明向右70,向下50,第三個參數(shù)無意義。
end
AddClassPostConstruct("widgets/controls", addHelloWidget) -- 這個函數(shù)是官方的MOD API,用于修改游戲中的類的構(gòu)造函數(shù)。第一個參數(shù)是類的文件路徑,根目錄為scripts。第二個自定義的修改函數(shù),第一個參數(shù)固定為self,指代要修改的類。

成果展示

開啟MOD,隨便選個角色進(jìn)入游戲,你會在屏幕上方看到Hello Klei的字樣

demo.jpg

常用Widget

官方已經(jīng)編寫好了大量可用的Widget,包含了大量基本功能,聯(lián)機版更有許多模板可以直接使用。我們進(jìn)行圖形界面編程時,通常不需要再費時費力地從頭編寫一個全新的Widget,大多數(shù)時候只需要使用官方提供的Widget進(jìn)行組合,甚至直接使用模板就足夠了。
這里只介紹一些常用的Widget及其子類,說明基本功能和使用場景。在后續(xù)教程里會對常用的Widget和模板進(jìn)行詳細(xì)介紹,并提供可參考的實例。


Text/文本

文本類Text主要用于文本呈現(xiàn)和處理。
基類為Text,有一個擴展子類:TextEdit

核心函數(shù)

構(gòu)造函數(shù)
: 文本類的主要功能就是文本呈現(xiàn),而類的構(gòu)造函數(shù)可以直接定義文本該以怎樣的形式呈現(xiàn)(字體,大小,內(nèi)容,顏色)

Text/文本

Text只提供文本呈現(xiàn)功能,能夠設(shè)置文本的字體,大小,內(nèi)容和顏色。Text的使用范圍十分廣泛,任何需要呈現(xiàn)文字的地方都需要用到Text。

TextEdit/文本編輯

TextEdit在文本呈現(xiàn)的基礎(chǔ)上,額外提供了文本編輯功能,主要用于各種輸入框,如聊天輸入框,控制臺輸入框等等。
它還有一個很特殊的擴展子類TextEditLinked,用于禮品兌換碼的輸入框,一般不使用。

FollowText/跟隨文本

跟隨文本類FollowText,和Text很像,但不是Text的子類。與Text的區(qū)別在于它的位置是動態(tài)變化的。常見應(yīng)用于顯示動作的名字,比如,當(dāng)你手持斧頭時,把光標(biāo)移動到樹上,會出現(xiàn)兩個字——砍樹。


Image/圖片

圖片類Image,主要用于圖片呈現(xiàn),沒有子類。

核心函數(shù)

構(gòu)造函數(shù)
: 圖片類和文本類相似,主要功能就是圖片呈現(xiàn),可以定義圖片的atlas文件和tex名。


Button/按鈕

按鈕類Button主要提供一個點擊操作。通過設(shè)定點擊操作觸發(fā)的函數(shù),讓玩家可以通過執(zhí)行某些功能。

類名 描述
ImageButton 圖片按鈕,最常用
TextButton 文字按鈕,偶爾會用
ListCursor 列表游標(biāo),和拖動條聯(lián)合使用。常用場景為服務(wù)器列表
AnimButton 動畫按鈕,極少使用
UIAnimButton 界面動畫按鈕,極少使用

基類為Button,子類如下表:

類名 描述
ImageButton 圖片按鈕,最常用
TextButton 文字按鈕,偶爾會用
ListCursor 列表游標(biāo),和拖動條聯(lián)合使用。常用場景為服務(wù)器列表
AnimButton 動畫按鈕,極少使用
UIAnimButton 界面動畫按鈕,極少使用

基類Button僅僅定義了點擊觸發(fā)函數(shù)的功能,但沒有定義它該以何種形式來呈現(xiàn)在玩家操作界面上。在實際使用中,通常不直接使用基類Button,而是根據(jù)情況使用它的各種子類,其中最為常用的是ImageButton。

核心函數(shù)

按鈕的主要功能就是在點擊后觸發(fā)函數(shù),因此設(shè)置點擊觸發(fā)函數(shù)的函數(shù)就是核心函數(shù)。

SetOnDown( fn )
: 設(shè)置按下按鈕彈起前觸發(fā)的函數(shù)

SetOnClick(fn)
: 設(shè)置按下按鈕彈起后觸發(fā)的函數(shù)

以上兩個設(shè)置函數(shù)里設(shè)置的fn,是沒有參數(shù)的。

ImageButton/圖片按鈕

大多數(shù)按鈕都屬于圖片按鈕,可以直接在構(gòu)造圖片按鈕實例時傳入atlas(該按鈕圖片的統(tǒng)一管理xml文件), normal(一般狀態(tài)下的圖片,下面的類似), focus(聚焦?fàn)顟B(tài)), disabled(不可用狀態(tài)), down(按下狀態(tài)), selected(選中狀態(tài)), image_scale(圖片縮放大?。? image_offset(圖片偏移量)等一系列參數(shù)。
對于缺失的參數(shù),會使用缺省值代替。所以在使用時,不寫任何參數(shù)也是可以的。


Badge/徽章

徽章類Badge,主要用于呈現(xiàn)一個圓形物體的動畫,常見應(yīng)用是各種指示器:饑餓度、精神度、血量、木頭值(吳迪),通過設(shè)置動畫播放的百分比來指示某個數(shù)值的多少。

特別提醒:Badge使用的動畫通常是逆過來的,也就是100%的狀態(tài)在開端,0%的狀態(tài)在結(jié)尾。這是為了保證狀態(tài)為100%時一定能播放出相應(yīng)的動畫關(guān)鍵幀。(動畫的0幀一定能播放出來,但最后一幀則不一定)。

類名 描述
HungerBadge 饑餓指示器
SanityBadge 精神指示器
HealthBadge 血量指示器
BeaverBadge 木頭值指示器

基類為Badge,子類如下表:

類名 描述
HungerBadge 饑餓指示器
SanityBadge 精神指示器
HealthBadge 血量指示器
BeaverBadge 木頭值指示器

核心函數(shù)

構(gòu)造函數(shù)
: animname, states分別指明要使用的動畫build/bank名(build和bank名必須一致)和anim名。通常的使用方式是,拓展成一個新的子類,在父類構(gòu)造函數(shù)中填寫animname和states,具體可以參考已有的官方子類。

SetPercent(val, max)
: 設(shè)置動畫播放的百分比。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,035評論 4 61
  • ¥開啟¥ 【iAPP實現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 7,295評論 0 17
  • 漢代·劉向《新序·雜事五》:“葉公子高好龍,鉤以寫龍,鑿以寫龍,屋室雕文以寫龍。于是天龍聞而下之,窺頭于牖,施尾于...
    清凈墨蓮閱讀 533評論 0 0
  • 學(xué)生公寓樓下掛著一個牌子: 請畢業(yè)生盡快搬離學(xué)生公寓并到值班處退還寢室鑰匙。 今年夏天悄然而至,如同往常一樣,沒有...
    大白兔奶精閱讀 6,012評論 11 27

友情鏈接更多精彩內(nèi)容