前言
mudlet内置强大的UI组件和API函数,让玩家可以很容易的改造界面,如下图效果:
关于UI相关的API文档
API文档很详细,也很强大,但就像是程序员设计网页一样,如果从零用代码一点点写太低效,而且学习成本高,如果通过封装好的框架可以让工作变的更简单,而这就是Geyser UI框架的作用,这个框架也是内置在mudlet客户端中的,不需要安装什么模块,直接可用。
关于GeyserUI的详细文档
问题是,对我们这些小白玩家来说学习Geyser框架也是有点麻烦的,为了让大家更容易使用,这里提供一个基础模版,通过基础模板可以快速改造游戏UI。
Geyser UI Template界面效果如下:
Geyser UI Template
下面本教程根据模版讲解UI的基础知识来学习GeyserUI框架的使用。
关于Geyser模版的一些基础知识在让客户端拥有一个独一无二的皮肤——Mudlet UI 设计(一)这篇教程中有比较详细的介绍,这里不再重复,建议大家先看看。
模版模块的安装非常简单,直接在你的mudlet客户端输入以下指令
lua installPackage([[https://mud.ren/storage/GeyserUITemplate.zip]])
安装后你的界面上多了一些组件,打开脚本会看到以下内容:
这里分二部分:CSSman和GUI,其中CSSman是由vadi大神封装的css脚本,让UI中使用css变的更方便,我们在改UI时不要动这个脚本,而是只动GUI下面的代码。
现在根据模版代码学习相关使用,包括基本UI函数介绍、CSSman组件的使用和Geyser框架的使用。
模版在GUI组上声明了一个GUI对象,我们的所有UI组件功能都这在这个对象中实现:
GUI = GUI or {}
Set Borders
在模版中的UI包括了7个box,12个icon和4个状态条,和做网页一样,在设置UI时要先布局,在mudlet中是设置border,Border
意思是边框,在mudlet中这个Border是游戏区域以外的地方,游戏内容不会显示在Border区域。
看看模版代码:
local w,h = getMainWindowSize()
setBorderLeft(w/4)
setBorderTop(h/10)
setBorderBottom(h/10)
setBorderRight(w/4)
这里的几个函数都是mudlet的API,getMainWindowSize()
是获取游戏界面的大小,返回值是宽和高(可以直接在命名行输入lua getMainWindowSize()
看看)。setBorderLeft()
等是设置左、上、下、右的Border大小,模板中设置的是左右1/4宽度,上下1/10高度。
关于Border的设置除了以上的4个函数,还有一个setBorderSizes()
可用,介绍如下:
setBorderSizes(top, right, bottom, left)
4个参数,具体指定上、右、下、左的值。
setBorderSizes(top, width, bottom)
3个参数,具体指定上、左右、下的值,这里左右宽度都是width。
setBorderSizes(height, width)
2个参数,指定上下的高度为height,左右的宽度为width。
setBorderSizes(size)
1个参数,上下左右的Border值都为size。
setBorderSizes()
没有参数,取消Border(Border的值为0)。
Create Background
Mudlet界面区域画好了,下面开始分区域并设置背景样式,直接看代码:
GUI.BackgroundCSS = CSSMan.new([[
background-color: rgb(20,0,20);
]])
GUI.Left = Geyser.Label:new({
name = "GUI.Left",
x = 0, y = 0,
width = "25%",
height = "100%",
})
GUI.Left:setStyleSheet(GUI.BackgroundCSS:getCSS())
GUI.Right = Geyser.Label:new({
name = "GUI.Right",
x = "-25%", y = 0,
width = "25%",
height = "100%",
})
GUI.Right:setStyleSheet(GUI.BackgroundCSS:getCSS())
GUI.Top = Geyser.Label:new({
name = "GUI.Top",
x = "25%", y = 0,
width = "50%",
height = "10%",
})
GUI.Top:setStyleSheet(GUI.BackgroundCSS:getCSS())
GUI.Bottom = Geyser.Label:new({
name = "GUI.Bottom",
x = "25%", y = "90%",
width = "50%",
height = "10%",
})
GUI.Bottom:setStyleSheet(GUI.BackgroundCSS:getCSS())
代码中使用CSSMan
创建了css样式GUI.BackgroundCSS
,使用Geyser.Label
创建了4个Label并指定了位置、大小和css样式(设置了背景颜色)。
Label做为内容(图片或文字)的载体,类似html中的<span>
标签,注意:为什么不说Label
类似<div>
标签?因为在Geyser中有一个Container
,这个做为容器,更类似于<div>
的作用。
这里重点介绍一下在布局时的x、y、width、height相关的知识:mudlet界面中(0,0)坐标是左上角位置,x/y是布局的起始坐标位置,这个坐标是Label左上角的坐标,正值为相对左和上的边距,如果为负值则是相对右和下的边距。width和height为Label的宽和高。不管是坐标还是宽高,值可以是绝对值也可以是相对值,可以带单位,如果不带单位默认为px
,甚至可以用数***算,以下示例为合法的取值:
{x = "20px", y = "-10c", width = "100%-30px", height = 30}
关于CSSman的用法
创建一个CSS对象:
mycssobject = CSSMan.new([[
background-color: rgb(26,26,26);
border-width: 1px;
border-color: green;
border-style: solid;
border-radius: 7;
font-family: Han Solo;
]])
-- 如果没有初始CSS样式,可以使用以下方式创建一个空的tracker
mycssobject = CSSMan.new([[]])
-- 或:
mycssobject = CSSMan.new("")
单独设置样式:
mycssobject:set("font-family", "Ubuntu")
取具体样式的值:
print(mycssobject:get("font-family"))
为标签设置具体css样式:
setLabelStyleSheet("myLabel", mycssobject:getCSS())
-- 或:
myLabel:setStyleSheet(mycssobject:getCSS())
Header Icons
前面的Label只是为画好的区域设置了背景颜色,这里则是增加具体UI了,先看代码:
GUI.Header = Geyser.HBox:new({
name = "GUI.Header",
x = 0, y = 0,
width = "100%",
height = "100%",
}, GUI.Top)
GUI.IconCSS = CSSMan.new([[
background-color: rgba(0,0,0,100);
border-style: solid;
border-width: 1px;
border-color: white;
border-radius: 5px;
margin: 5px;
qproperty-wordWrap: true;
]])
for i=1,12 do
GUI["Icon"..i] = Geyser.Label:new({
name = "GUI.Icon"..i,
},GUI.Header)
GUI["Icon"..i]:setStyleSheet(GUI.IconCSS:getCSS())
GUI["Icon"..i]:echo("<center>GUI. Icon"..i)
end
代码中生成了12个用来做Icon的Label,从代码上看这里新用到了Geyser.HBox
,在Geyser中HBox/VBox
是特殊的容器对象,位于其中的元素将被水平或垂直对齐。代码使用GUI["Icon"..i]:echo("<center>GUI. Icon"..i)
设置每个标签的文字内容为GUI.Icon1
~GUI.Icon12
。
模版代码只是占了位置,并没有实现具体的功能,下面我们自己完善一下,如下示例,设置Icon1为资料
,当玩家点击后会显示score
的内容,同理Icon2为物品
,Icon3为技能
:
function cmd(cmd)
send(cmd)
end
GUI.Icon1:setClickCallback("cmd", "score")
GUI.Icon1:echo("<center>资料")
GUI.Icon2:setClickCallback("cmd", "i")
GUI.Icon2:echo("<center>物品")
GUI.Icon3:setClickCallback("cmd", "cha")
GUI.Icon3:echo("<center>技能")
这里重点是使用了setClickCallback()
这个Geyser框架提供的回调函数,作用是点击Label时执行指定函数。cmd
是我个自己实现的函数,作用就是发送指令到游戏,具体使用mudlet提供的send()
函数。
下面我们增加一点演示:
GUI.Icon10:setClickCallback("openWebPage", "https://bbs.mud.ren/nodes/6")
GUI.Icon10:echo("<center>BBS")
GUI.Icon11:setClickCallback("receiveMSP", "!!MUSIC(1001.mp3 L=1 V=100 U=https://mud.ren/storage/wav/)")
GUI.Icon11:echo("<center>Music")
这里我们设置Icon10的按钮点击访问网页,Icon11就更骚了,点击可以播放音乐。
Gauges
而在模版提供的功能中有一个属性条,这个使用的是Geyser.Gauge
组件,可以很方便的显示玩家属性值,具体方式为Gauge:setValue(当前值,最大值)
,如:
GUI.Health:setValue(50, 100)
模版的具体代码如下:
GUI.Footer = Geyser.HBox:new({
name = "GUI.Footer",
x = 0, y = 0,
width = "100%",
height = "100%",
},GUI.Bottom)
GUI.LeftColumn = Geyser.VBox:new({
name = "GUI.LeftColumn",
},GUI.Footer)
GUI.RightColumn = Geyser.VBox:new({
name = "GUI.RightColumn",
},GUI.Footer)
GUI.GaugeBackCSS = CSSMan.new([[
background-color: rgba(0,0,0,0);
border-style: solid;
border-color: white;
border-width: 1px;
border-radius: 5px;
margin: 5px;
]])
GUI.GaugeFrontCSS = CSSMan.new([[
background-color: rgba(0,0,0,0);
border-style: solid;
border-color: white;
border-width: 1px;
border-radius: 5px;
margin: 5px;
]])
GUI.Health = Geyser.Gauge:new({
name = "GUI.Health",
},GUI.LeftColumn)
GUI.Health.back:setStyleSheet(GUI.GaugeBackCSS:getCSS())
GUI.GaugeFrontCSS:set("background-color","red")
GUI.Health.front:setStyleSheet(GUI.GaugeFrontCSS:getCSS())
GUI.Health:setValue(math.random(100),100)
GUI.Health.front:echo("GUI.Health")
GUI.Mana = Geyser.Gauge:new({
name = "GUI.Mana",
},GUI.LeftColumn)
GUI.Mana.back:setStyleSheet(GUI.GaugeBackCSS:getCSS())
GUI.GaugeFrontCSS:set("background-color","blue")
GUI.Mana.front:setStyleSheet(GUI.GaugeFrontCSS:getCSS())
GUI.Mana:setValue(math.random(100),100)
GUI.Mana.front:echo("GUI.Mana")
GUI.Endurance = Geyser.Gauge:new({
name = "GUI.Endurance",
},GUI.RightColumn)
GUI.Endurance.back:setStyleSheet(GUI.GaugeBackCSS:getCSS())
GUI.GaugeFrontCSS:set("background-color","yellow")
GUI.Endurance.front:setStyleSheet(GUI.GaugeFrontCSS:getCSS())
GUI.Endurance:setValue(math.random(100),100)
--GUI.Endurance.front:echo("GUI.Endurance")
GUI.Endurance.front:echo([[<span style = "color: black">GUI.Endurance</span>]])
GUI.Willpower = Geyser.Gauge:new({
name = "GUI.Willpower",
},GUI.RightColumn)
GUI.Willpower.back:setStyleSheet(GUI.GaugeBackCSS:getCSS())
GUI.GaugeFrontCSS:set("background-color","purple")
GUI.Willpower.front:setStyleSheet(GUI.GaugeFrontCSS:getCSS())
GUI.Willpower:setValue(math.random(100),100)
GUI.Willpower.front:echo("GUI.Willpower")
本部分代码看起来多一些,但其实也很简单,这里不做过多说明,主要就是使用Geyser.HBox
和Geyser.VBox
布局,把属性条使用Geyser.Gauge
加到布局上,并指定了样式了值,这里的值是随机生成的,我们可以改成从游戏中取得的玩家的真实属性值。
Boxes
这里的模板代码则是把前面的Border布局细分为不同的功能模块,通过以下代码一共分了7个Box:
GUI.BoxCSS = CSSMan.new([[
background-color: rgba(0,0,0,100);
border-style: solid;
border-width: 1px;
border-radius: 10px;
border-color: white;
margin: 10px;
]])
GUI.Box1 = Geyser.Label:new({
name = "GUI.Box1",
x = 0, y = 0,
width = "100%",
height = "50%",
},GUI.Right)
GUI.Box1:setStyleSheet(GUI.BoxCSS:getCSS())
GUI.Box1:echo("<center>GUI.Box1")
GUI.Box2 = Geyser.Label:new({
name = "GUI.Box2",
x = 0, y = "50%",
width = "50%",
height = "50%",
},GUI.Right)
GUI.Box2:setStyleSheet(GUI.BoxCSS:getCSS())
GUI.Box2:echo("<center>GUI.Box2")
GUI.Box3 = Geyser.Label:new({
name = "GUI.Box3",
x = "50%", y = "50%",
width = "50%",
height = "50%",
},GUI.Right)
GUI.Box3:setStyleSheet(GUI.BoxCSS:getCSS())
GUI.Box3:echo("<center>GUI.Box3")
GUI.Box4 = Geyser.Label:new({
name = "GUI.Box4",
x = "0%", y = "0%",
width = "100%",
height = "25%",
},GUI.Left)
GUI.Box4:setStyleSheet(GUI.BoxCSS:getCSS())
GUI.Box4:echo("<center>GUI.Box4")
GUI.Box5 = Geyser.Label:new({
name = "GUI.Box5",
x = "0%", y = "25%",
width = "50%",
height = "50%",
},GUI.Left)
GUI.Box5:setStyleSheet(GUI.BoxCSS:getCSS())
GUI.Box5:echo("<center>GUI.Box5")
GUI.Box6 = Geyser.Label:new({
name = "GUI.Box6",
x = "50%", y = "25%",
width = "50%",
height = "50%",
},GUI.Left)
GUI.Box6:setStyleSheet(GUI.BoxCSS:getCSS())
GUI.Box6:echo("<center>GUI.Box6")
GUI.Box7 = Geyser.Label:new({
name = "GUI.Box7",
x = "0%", y = "75%",
width = "100%",
height = "25%",
},GUI.Left)
GUI.Box7:setStyleSheet(GUI.BoxCSS:getCSS())
GUI.Box7:echo("<center>GUI.Box7")
这里就是很简单的布局方面的事了,不多做解释,我们可以直接改这里的代码自己重新布局,比如炎黄MUD就是在这个基础上把Box4~7移除了,只保留了Box1~3。
模版提供的布局可以很方便的修改为我们需要的功能,比如,我们把地图嵌入到我们布局的Box1中,演示代码如下:
GUI.Map_Container = Geyser.Container:new({
name = "GUI.Map_Container",
x = 0, y = 0,
width = "100%",
height = "100%",
},GUI.Box1)
GUI.Mapper = Geyser.Mapper:new({
name = "GUI.Mapper",
x = 20, y = 20,
width = GUI.Map_Container:get_width()-40,
height = GUI.Map_Container:get_height()-40,
},GUI.Map_Container)
GeyserUI相关使用教程
在通过模版讲解使用Geyser框架时没有用到图片,因为个人来说用UI只是方便游戏,而不是为了做一个美观的界面,图片界面的制作其实就是使用CSS插入背景图片素材,并不难,如果你有兴趣,以下是本站其他玩家分享的UI框架实战教程,可以学习参考。
- 让客户端拥有一个独一无二的皮肤——Mudlet UI 设计(一)
- 用mudlet的Geyser.Gauge功能制作北大侠客行的图形化血条
- 用mudlet实现机器人查岗图片浮窗(北大侠客行fullme)
另外一种学习方式是运行mudlet游戏列表中的国外游戏(如:Midnight Sun 2),直接看看别人的代码学习。