
因为我是新手,只能做一个非常简单的插件,21点扑克游戏。比较有趣吧,插件也可以做一个游戏?游戏中的游戏!
总结下跟一般的编程一样的。
运行效果查看:魔兽世界客户端+试玩账户
编辑器:首推NotePad++,SciTE,AddOn Studio
调试:!BugGrabber,BugSack,TinyPad + print(“”) ,print 可以在游戏中打印日志,我们可以打印变量来调试。
教程:《Beginning Lua with World of Warcraft Add-ons》

当然不能每次重启魔兽世界客户端来看修改效果,我们可以做一个简单的宏来重载所有UI,当你修改了你的插件的XML或者Lua文件时,可以重载所有UI来看到修改效果。当然Shift+点击BugSack也有同样的效果。修改toc或者新增图片,音乐资源是不能靠重载UI来生效的,要重启魔兽世界客户端。
把上面提到的三个插件!BugGrabber,BugSack,TinyPad,google下,都下载下来。拷贝到\Interface\AddOns 目录下。进入游戏,输入/pad 就可以打开TinyPad了,我们输入print(“Hello World”),再点击上面的菜单有个功能是run this page as a script,就可以看到效果了。


点击Click按钮就会调用我们一个Lua函数,点击Close,整个界面就会隐藏。

这次是一个完整的插件,名字叫testButton,包括三个文件:
Frame.lua — 用来存放脚本
Frame — 用来描述界面,以XML编写
testButton.toc — 用来描述我们的插件,比如插件支持的魔兽世界版本,插件名字,插件作者,插件包含文件等等。
先来看下testButton.toc
|
1
2
3
4
5
6
|
##
Author: Walle##
Interface: 50400##
Title: testButton##
Version: 1.0Frame.xmlFrame.lua |
再看下xml,里面有两个button
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
<Ui
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.blizzard.com/wow/ui/"> <Frame
name="Frame1"
parent="UIParent"
toplevel="true"
enableMouse="true"
movable="true"
clampedToScreen="true"> <Size> <AbsDimension
x="200"
y="200"
/> </Size> <Anchors> <Anchor
point="CENTER"> <Offset
x="-35"
y="34"
/> </Anchor> </Anchors> <Backdrop
bgFile="Interface\DialogFrame\UI-DialogBox-Background"
edgeFile="Interface\DialogFrame\UI-DialogBox-Border"
tile="true"> <BackgroundInsets> <AbsInset
left="11"
right="12"
top="12"
bottom="11"
/> </BackgroundInsets> <TileSize> <AbsValue
val="32"
/> </TileSize> <EdgeSize> <AbsValue
val="32"
/> </EdgeSize> </Backdrop> <Frames> <Button
name="BtnClose"
inherits="UIPanelButtonTemplate"
text="Close"> <Size> <AbsDimension
x="75"
y="23"
/> </Size> <Anchors> <Anchor
point="TOPLEFT"> <Offset
x="69"
y="-134"
/> </Anchor> </Anchors> <Scripts> <OnClick> self:GetParent():Hide() </OnClick> </Scripts> </Button> <Button
name="BtnClick"
inherits="UIPanelButtonTemplate"
text="Click"> <Size> <AbsDimension
x="75"
y="23"
/> </Size> <Anchors> <Anchor
point="TOPLEFT"> <Offset
x="69"
y="-100"
/> </Anchor> </Anchors> <Scripts> <OnClick> BtnClick() </OnClick> </Scripts> </Button> </Frames> <Scripts> <OnLoad> self:RegisterForDrag("LeftButton") </OnLoad> <OnDragStart> self:StartMoving() </OnDragStart> <OnDragStop> self:StopMovingOrSizing() </OnDragStop> </Scripts> </Frame></Ui> |
这个XML看起来有点复杂,可以用Addon Studio 建一个项目,拖个按钮进去,玩玩。就大致了解上面的东西了。无论是Frame还是Button等都有大小用下面的来表示一个200×200的。
<Size>
<AbsDimension x=”200″ y=”200″ />
</Size>
Anchors 来表示位置。point可以设置CENTER,TOP,LEFT等等,下面的Offset是偏移量,比如你设置了CENTER,那么-35就是中心偏左35。
<Anchors>
<Anchor point=”CENTER”>
<Offset x=”-35″ y=”34″ />
</Anchor>
</Anchors>
Backdrop表示Fram的边框,直接从Addon Studio抄下来。
我们注意到Button有个属性是inherits,继承的意思
inherits=”UIPanelButtonTemplate” 这里表示简单的继承了WOW原生的按钮样式,按钮可以设置非常复杂的样式,这里不再赘述,大家可以参考WOW API。
XML中都可以加脚本,比如这里:
<Scripts>
<OnClick>
self:GetParent():Hide()
</OnClick>
</Scripts>
它的效果就是简单的使整个都隐藏起来。
我们对整个Frame还增加了拖动效果。
还有必须说明的是一般用XML能实现的,直接用Lua代码也可以的。
比如设置宽度,高度,可以这样写:
Frame1:SetWidth(500)
Frame1:SetHeight(500)
大家可以在tinypad中,执行看下效果。不单单是改变属性,创建一个按钮也可以用Lua代码的。大家可以去Google。
最后看下Frame.lua
它里面就是一个简单的function:
function BtnClick()
print (“BtnClick”)
end
回到我们的扑克游戏来。
懂的童鞋就直接可以跳过了,容我摘抄一段:
21点一般用到1-8副牌。庄家给每个玩家发两张牌,一张牌面朝上(叫明牌),一张牌面朝下(叫暗牌);给自己发两张牌,一张暗牌,一张明牌。大家手中扑克点数的计算是:K、Q、J 和 10 牌都算作 10 点。A 牌既可算作1 点也可算作11 点,由玩家自己决定。其余所有2 至9 牌均按其原面值计算。首先玩家开始要牌,如果玩家拿到的前两张牌是一张 A 和一张10点牌,就拥有黑杰克(Blackjack);此时,如果庄家没有黑杰克,玩家就能赢得2倍的赌金(1赔2)。如果庄家的明牌有一张A,则玩家可以考虑买不买保险,金额是赌筹的一半。如果庄家是blackjack,那么玩家拿回保险金并且直接获胜;如果庄家没有blackjack则玩家输掉保险继续游戏。没有黑杰克的玩家可以继续拿牌,可以随意要多少张。目的是尽量往21点靠,靠得越近越好,最好就是21点了。在要牌的过程中,如果所有的牌加起来超过21点,玩家就输了——叫爆掉(Bust),游戏也就结束了。假如玩家没爆掉,又决定不再要牌了,这时庄家就把他的那张暗牌打开来。一般到17点或17点以上不再拿牌,但也有可能15到16点甚至12到13点就不再拿牌或者18到19点继续拿牌。假如庄家爆掉了,那他就输了。假如他没爆掉,那么你就与他比点数大小,大为赢。一样的点数为平手,你可以把你的赌注拿回来。
没做这个游戏之前我也大致知道21点游戏规则,没有想到还有个保险的东西。大家可以去搜下有关21点的flash游戏来玩下。
老实说,我写这个插件不是为了写一个帮助的插件,是想要学习下Lua的语法。所以看《Programming in Lua, 3rd Edition》就很有必要。
下面只是列举下一些非常基础的Lua语法,用来做我们这次《21点扑克游戏》足够用了。21点扑克游戏,我写了一个函数来得到手里牌的总的值。我们知道A这个牌比较特殊,即可当1,也可做11,但不可能有两张牌都作为11,总的就是>=22就爆掉了。下面这个函数比较简单,先尝试循环所有的牌,对值相加,如果没有A的话就直接返回,如果有A的话,尝试把它以11点来算,如果没爆的话就是最佳值。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
function
GetTotalValue(cards) local
containAce = false
--//变量用local关键词,没有local就是全局变量 local
totalValue = 0 local
anotherTotalValue = 0 for
i, v in
ipairs(cards) do
--//for
循环 totalValue
= totalValue + v.value if
v.value == 1 then --//if
列子 containAce
= true end
--//if
结束 end
--//for
循环结束 if
containAce then anotherTotalValue
= totalValue + 10 --//
change Ace‘s value to 11 end if
containAce and anotherTotalValue <= 21 then return
anotherTotalValue end return
totalValueend |
简单解释下就是Lua中可以以一行作为结束,都不用加;,局部变量前缀是local,有点像Javascript中的var,但Lua的Local也可以直接不写就是全局变量了。Lua会有很多end,for循环结束有end,if结束也有end,function结束也是end。C++ 中的 && 和 || 在 Lua中是 and 和 or,另外 C++中的 != 在 Lua 中是 ~=
Lua中最重要的就是Table,它没有Javascript中的Array,但这个Table比Array还要强大。再来看一个例子,是我们这个游戏的初始化牌的方法。总共牌共有52张。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
POKER_CARD_NAME
= "%s
of %s"POKER_CARDS
= { --//Table好像内部是一个hashtable,所以可以这样用。这样POKER_CARDS["K"]
就== "King"了 K
= "King", Q
= "Queen", J
= "Jack", ["10"]
= "Ten", ["9"]
= "Nine", ["8"]
= "Eight", ["7"]
= "Seven", ["6"]
= "Six", ["5"]
= "Five", ["4"]
= "Four", ["3"]
= "Three", ["2"]
= "Two", A
= "Ace",}POKER_SUITS
= { H
= "Hearts", D
= "Diamonds", C
= "Clubs", S
= "Spades",}local
ranks = {"K",
"Q",
"J",
"10",
"9",
"8",
"7",
"6",
"5",
"4",
"3",
"2",
"A"}
--//也可以直接初始话这样,index是用1开始的比较奇怪。local
suits = {"H",
"D",
"C",
"S"}local
cards = {}local
cardsByRank = {}local
value = 10for
i, r in
ipairs(ranks) do cardsByRank[r]
= {} for
i, s in
ipairs(suits) do cards[#cards
+ 1] = { --// #cards可以得到cards这个table的长度,这里每个card又是一个table rank
= POKER_CARDS[r], suit
= POKER_SUITS[s], name
= POKER_CARD_NAME:format(POKER_CARDS[r], POKER_SUITS[s]), --//string类型中有简单的format语法 code
= r..s, value
= value } cardsByRank[r][s]
= cards[#cards] end if
i >= 4 then value
= value - 1 endend |
我们这个插件游戏中,需要用到扑克的图片。魔兽世界插件是支持图片显示的,用Frame中的texture就可以了。具体大家可以看代码,图片格式支持两种,一种是TGA,另外一种我忘了。图片大小比较变态,要(2的n次方) x (2的n次方)。比如一个64×128就是合格的图片大小。
魔兽世界插件也支持音乐播放,好像支持mp3格式和ogg格式。大家可以用”格式工厂”软件来转换。播放音乐的API是PlaySoundFile,参数是路径。
function InsurancePayMusic()
PlaySoundFile(“Interface\\AddOns\\BlackJack\\sounds\\ins_pay.ogg”)
end
http://www.waitingfy.com/?attachment_id=1053
也可以访问github地址:https://github.com/waitingfy/BlackJack
http://www.waitingfy.com/archives/1047
《魔兽世界插件》教程—21点扑克游戏 Blackjack,布布扣,bubuko.com
原文:http://blog.csdn.net/xiebaochun/article/details/23356309