解析LUA快速入手指南
LUA快速入手指南是本文要介紹的內容,主要是來學習LUA在游戲中使用方法,具體內容來看本文詳解。TOC工程描述文件后綴名為toc的文件就是工程文件,包含工程的基本信息。主要包含以下內容:
切換行號顯示
- ## Interface: 適用的魔獸版本號
- ## Title: 顯示的標題(默認語言)
- ## Notes: 顯示的說明(默認語言)
- ## Title-zhCN: 特定語言的標題(簡體中文)
- ## Notes-zhCN: 特定語言的說明(簡體中文)
- ## Author: 作者(不顯示)
- ## Version: 版本
- ## eMail: 如題
- ## UIType: 插件類型
- ## Dependencies: 依賴的插件
- ## RequiredDeps: 必須依賴的其他插件
- ## OptionalDeps: 可選倚賴
- ## SavedVariables: 統一存放的變量
- ## SavedVariablesPerCharacter: 按角色存放的變量
- ## LoadOnDemand: 1 (調用時加載)
- ## LoadWith: 當指定插件加載時才加載,前提是調用時加載
- ## DefaultState: disabled 默認狀態
- ## Secure: 安全(功能未知)
- # 注釋1 dklasjfkasdj
- Script.lua -- 腳本文件
- % 注釋2 dskajfklasdjfklsdaj
- Layout.xml -- 布局文件
‘#’ 和 ‘%’ 為行注釋符號。
而以##開頭的注釋行可就不光是好看的了,這些都是插件的工程描述標記,要是不注意插件根本就不會載入。
示例中彩色的標記表示標準標記,每個標準標記都有特定功能。其它eMail, Author等為擴展標記,只有注釋功能。
工程標記之后的部分為包含文件列表,腳本文件和布局文件,數量隨意,但每種至少要有一個:一個lua或一個xml。
包含文件列表中的順序對應著載入順序,非常要緊!
如果要寫中文,一定要將toc文件保存為UTF-8格式,否則無法正確識別。方法很簡單:用記事本打開,另存為,選擇編碼就行;文件格式要選所有文件,否則會存成txt文件。
建議你多下幾個插件,打開看看,參考一下。
XML —— 屏幕布局描述文件在魔獸插件中使用XML來描述UI的屏幕布局。
注釋符號:<!-- 注釋內容 --> 。
如果要寫中文注釋,必須在XML文件開頭添加一行:
- <?xml version="1.0" encoding="UTF-8"?>
XML文件主要內容一個XML文件往往包含以下內容:
- <!-- Ui標簽是包含所有其它標簽的根標簽 -->
- <Ui xmlns="http://www.blizzard.com/wow/ui/"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.blizzard.com/wow/ui/
- C:\Projects\WoW\Bin\Interface\FrameXML\UI.xsd">
- <Script file="localization.lua"/> <!-- 在此載入用于漢化的lua文件 -->
- <Frame name="zBar" parent="UIParent"> <!-- 一個Frame框架 -->
- <Scripts> <!-- 腳本部分,用于處理事件 -->
- <OnLoad>
- zBar_OnLoad();
- </OnLoad>
- <OnEvent>
- zBar_OnEvent(event);
- </OnEvent>
- </Scripts>
- </Frame>
- </Ui>
Ui標簽<Ui>是最上級標簽。其中的schema用來語法檢查,如果你的XML編輯器支持還可以用來代碼提示。否則對我們來說用處不大。可以簡化為:
- <Ui xmlns="http://www.blizzard.com/wow/ui/"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
</Ui>或者更加簡化,不太規范但是可用:<Ui>布局內容</Ui>
Script標簽在Ui標簽中最先包含的往往是<Script file="lua 文件名"/>表示在此處載入某lua文件。
注意這里也有順序哦,如果發現變量、函數不存在,檢查一下看是不是順序問題。
這樣一來我們有了兩種方法載入lua文件。在xml中載入lua實際上不是非如此不可的,有時候沒必要用xml的就直接在toc中放個lua,把xml省掉。這樣做你必須在lua中有個入口,也就是有個裸語句(不在任何function中的)進行事件注冊或者調用函數。
Frame標簽XML中最主要的一個標簽是<Frame></Frame>。所謂Frame意指框架,就是用來包含其他東西的。
UIParent是最上層的框架,所有的UI都包含在其中。與之并列的是一個特殊框架World Frame,包括FPS、截圖。
其它控件一般都是Frame的子類,都包含類似的屬性和子標簽:背景、貼圖、邊框、事件處理。如:<button> <slider> <statusbar> 等等。
Frame標簽就像一個透明的玻璃容器。你可以僅用它來裝載其它部件,當然也可以給他添加貼圖顯示出來。
記得游戲中按下“Alt+z”的效果了么,被隱藏的就是UIParent。容器被隱藏了,里面裝的東西也就透明了。
子標簽和屬性
- <Frame name="名稱,唯一" inherits="myFather繼承" toplevel="true等級" parent="UIParent父標簽" id="編號"
- movable="true可移動" enableMouse="true允許鼠標事件" frameStrata="HIGH層級" hidden="false隱藏" >
- <Size> <!--大小 -->
- <AbsDimension x="" y=""/> <!--絕對尺寸 -->
- </Size>
- <!-- 簡化寫法 -->
- <Size x="" y=""/>
- <Anchors> <!--錨點,用來標記相對位置 -->
- <Anchor Point="本控件的參考點" relativeTo="參考控件" relativePoint="參考控件的參考點">
- <Offset> <!-- 偏移值 -->
- <AbsDimension x="" y=""/>
- </Offset>
- <!-- 簡化寫法 -->
- <Offset x="" y="" />
- </Anchor>
- </Anchors>
- <!-- 背景和邊框 -->
- <Backdrop name="$parentBackdrop" bgFile="背景貼圖" edgeFile="邊框貼圖" tile="不知道">
- <EdgeSize>
- <AbsValue val="18"/> <!-- 邊框縮放大小 -->
- </EdgeSize>
- <TileSize>
- <AbsValue val="16"/>
- </TileSize>
- <BackgroundInsets>
- <AbsInset left="5" right="5" top="5" bottom="5"/> <!-- 背景四周留白 -->
- </BackgroundInsets>
- </Backdrop>
- <Layers> <!-- 分層,主要放置貼圖材質和字符 -->
- <Layer level="BACKGROUND"> <!-- 背景層 -->
- <Texture name="$parentRed" file="貼圖" hidden="true"/>
- </Layer>
- <Layer level="ARTWORK"> <!-- 藝術層 -->
- <FontString name="$parent名字" inherits="Font" justifyH="CENTER"/>
- <Layer level="OVERLAY"> <!-- 覆蓋層 -->
- <Texture name="$parentShine" file="貼圖" alphaMode="ADD透明模式" hidden="true">
- <Anchors>
- <Anchor point="CENTER"/>
- </Anchors>
- </Texture>
- </Layer>
- </Layers>
- <Frames>
- <!-- 嵌入其他框架 -->
- </Frames>
- <Scripts>
- <OnLoad>處理載入事件</OnLoad>
- <OnEvent>處理用RegisterEvent注冊過的事件</OnEvent>
- <OnUpdate>更新事件</OnUpdate>
- <OnShow>顯示事件</OnShow>
- <OnHide>隱藏事件</OnHide>
- <OnClick>單擊事件</OnClick>
- <OnDoubleClick>雙擊事件</OnDoubleClick>
- <OnEnter>鼠標進入</OnEnter>
- <OnLeave>鼠標移出</OnLeave>
- <OnDragStart>拖放開始</OnDragStart>
- <OnReceiveDrag>接受拖放</OnReceiveDrag>
- <OnValueChanged>值改變(用于Slider滑塊)</OnValueChanged>
- </Scripts>
- </Frame>
如圖:
UI對象的繼承關系UIObject
始祖,所有其他UI對象都由它繼承。
LayoutFrame
布局框架,繼承UIObject,主要有一些布局函數,(這是一個虛類不可創建實例)。
LayoutFrame的重要函數:GetParent() SetParent() GetAlpha() SetAlpha() SetWidth() SetHeight()
IsShown() 和 IsVisible() 的區別,如圖:
Frame
框架,繼承Layout Frame,最重要的UI對象,屏幕上可見的UI對象都是它的子類,一般用來在上面放置其他控件。Frame的子類;描述
- Button;按鈕。
- EditBox;可編輯文本框。
- GameTooltip;鼠標提示
- ColorSelect;顏色選擇器
- MessageFrame;信息框架
- Minimap;迷你地圖,小地圖、戰場地圖等
- Model;模型,用于顯示3D動畫。人物模型,冷卻都是Model
- MovieFrame;影像框架,放電影的。。。不知道怎么用
- ScrollFrame;可滾動框架
- ScrollingMessageFrame;滾動信息框架,例如聊天窗口、戰斗信息窗口
- SimpleHTML;簡單超文本標記語言,應該是類似網頁的可定義字體大小顏色式樣、帶圖片的文本
- Slider;滑快,像系統設置中的UI縮放那個滑快
- StatusBar;進度條,像是施法條,血條等等
LUA 腳本代碼文件 更深入的學習請閱讀本站的其它文章:ProgrammingInLua, 魔獸Api索引
如果你有一門以上的語言基礎,那么學習lua語言不是什么難事。
lua是一種靈活的語言,關于他的來源我并不知道多少,只談一下自己的感受。基本語法和Basic類似,或者說更像是Asp的腳本語言吧。但同時他又借鑒了Java的長處,更加的智能化、靈活。寫法多樣又方便不同習慣的人上手。
lua語法很簡單,相關資料也很多,我只列出需要注意的部分。
基本語法摘要行注釋符號:“--”
段注釋符號:“--” “”;實際上還是行注釋,而“” “”包圍的部分編譯器會認為是一行。
行結束符號:用“;”或者不寫都行,看你的習慣了,只要沒有歧義就好
NULL空值:在這里是nil
沒有指針:和Java一樣,沒指針的意思就是所有變量都是引用。要注意不是拷貝的副本,改變引用變量原始變量會同時改變。
變量作用域:默認是global(全局作用域),加上local前綴就是局部的了(文件內部作用域)。
函數作用域:和變量一樣默認是全局作用域。實際上函數也是變量。
數組,集合:只有一種,類似于。。。我也不知道類似什么。寫法也很隨意,舉例:
- Config = {
- attribute1 = "apple",
- attribute2 = false,
- ["attribute3"] = "animal",
- [1] = "Button1",
- ["2"] = "Cool",
- }
關于數組的就看上面的“Lua腳本語言入門”,講的很清楚。
關于布爾變量:要注意的是只有nil和false表示false,其他一律為true(包括0),而false是要占用引用內存的,建議把false一律換成nil。
關于布爾運算:lua里的布爾運算是很有趣的,也相當合理。注意運算的值并不是布爾值,而是其中一個操作數的值。
- x = a and b; -- 與運算,a為false則x等于a,a為true則x=b。
- x = a or b; -- 或運算,a為true則x等于a,a為false則x = b。
是不是有點暈?其實很合理。如果你一時繞不清楚,就只要記住結果好了。
布爾運算的妙用:我堅定地認為lua中的布爾運算實際上不是布爾運算,而是簡化了的條件語句。比如:
- x = a and b; --相當于:
- if (not a) then
- x = a;
- else
- x = b;
- end
- x = a or b; -- 相當于:
- if (a) then
- x = a;
- else
- x = b;
- end
還有一種簡化,常用于變量的初始化:
- xx = x or a; -- 相當于:
- if ( not x ) then
- x = a;
- end
對象在lua里,框架和控件都作為對象存在。 要引用在XML中定義的框架或控件,使用如下語句:
- frame = getglobal("FrameName");
對象的屬性
屬性在對象中就像集合成員一樣,屬性引用符號為:“.”,例如:frame.attribute1
對象實際上就是一個特殊集合!!
對象的屬性同樣可以用集合方式引用: frame["attribute2"]。函數調用也是一樣,見下面說明。
函數函數定義
類似Basic,例如:
- function add(a,b)
- local ret = a + b;
- return ret;
- end
覆蓋函數
函數定義實際上是把一個變量指向一段代碼。前面舉的例子含義是:把變量add指向一段函數代碼。 因此,我們可以很方便的覆蓋(Override)Blizzard的系統函數,只要把系統函數變量指向自己定義的函數代碼就可以了。以覆蓋上面的add函數為例,有幾種方法:-- 1. 把原函數變量指向新的函數代碼段
- old_add = add; -- 保存原始的add指向的函數
- add = function(a,b) -- add 指向新的代碼段
- if ( old_add(a,b) == 0 ) then return nil end
- return a + b
- end
2. 直接定義一個同名函數
function add(a,b) -- 含義與第一種方法相同:改變add的值,使它指向新的代碼段
- local ret = a + b
- if ( ret == 0 ) then return nil end
- return ret
- d
對象的函數
函數在對象中有些特別,調用符號為冒號:“:”,例如:frame:Show();
函數實際上是一種特殊變量
它指向一段代碼,更一般的調用符號和一般的對象屬性相同,為 “.”。 而特殊符號“:”實際上是在調用的時候多加了一個參數“self”,指代調用者本身。例如:
- Frame1:SetAlpha(0.5)
相當于
Frame1.SetAlpha( Frame1, 0.5)函數的默認參數
有一些函數參數比較特殊:對象事件處理函數,有一些有默認參數,例如OnClick OnMouseDown OnMouseUp;默認參數 arg1
OnEvent;默認參數event所以在定義這些函數的時候可以不寫參數:function zOnClick()
- if ( arg1 == "LeftButton" ) then
- doSomething()
- end
- d
但是要注意:如果函數定義里寫了參數,那么調用函數的時候一定要寫參數!!!!否則認為參數為nil。例如:
- <OnClick>if ( not this.lock ) then zOnClick(arg1) end</OnClick>
之所以有默認參數存在是因為在動態改變事件處理函數的時候不能寫參數,例如button:SetScript("OnClick", zOnClick)默認參數的原理
經過多方考證,這些默認參數均為全局變量。
實現默認參數得流程為:對象觸發事件時會調用對應函數,在其中將全局變量即默認參數賦值。
例如xml中有如下描述:
- <OnClick>zOnClick()</OnClick>
雖然不知道WoW虛擬機確切的處理方式,但我們可虛擬如下:-- 事件觸發時調用對象的事件處理函數
- Object:OnClick("LeftButton")
該處理函數定義模擬如下
- function Object:OnClick(arg1)
- zOnClick()
- end
- -- [[
由于arg1 為全局變量,對象被調用時 arg1 被賦值為"LeftButton"
其后Object:OnClick()中又馬上調用了zOnClick()插件處理函數,
其中并無被改變的機會,因此 arg1 被成功傳遞,看起來就像是默認參數了。
-- ]] 默認參數還包括 this,但是 self 不是全局變量。
小結:解析LUA快速入手指南的內容介紹完了,希望通過本文的學習能對你有所幫助!