Mudlet UI 基础教程-Geyser UI Template

前言

mudlet内置强大的UI组件和API函数,让玩家可以很容易的改造界面,如下图效果:

file file file

关于UI相关的API文档

API文档很详细,也很强大,但就像是程序员设计网页一样,如果从零用代码一点点写太低效,而且学习成本高,如果通过封装好的框架可以让工作变的更简单,而这就是Geyser UI框架的作用,这个框架也是内置在mudlet客户端中的,不需要安装什么模块,直接可用。

关于GeyserUI的详细文档

问题是,对我们这些小白玩家来说学习Geyser框架也是有点麻烦的,为了让大家更容易使用,这里提供一个基础模版,通过基础模板可以快速改造游戏UI。

Geyser UI Template界面效果如下:

file


Geyser UI Template

下面本教程根据模版讲解UI的基础知识来学习GeyserUI框架的使用。

关于Geyser模版的一些基础知识在让客户端拥有一个独一无二的皮肤——Mudlet UI 设计(一)这篇教程中有比较详细的介绍,这里不再重复,建议大家先看看。

模版模块的安装非常简单,直接在你的mudlet客户端输入以下指令

lua installPackage([[https://mud.ren/storage/GeyserUITemplate.zip]])

安装后你的界面上多了一些组件,打开脚本会看到以下内容:

file

这里分二部分: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.HBoxGeyser.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)

file


GeyserUI相关使用教程

在通过模版讲解使用Geyser框架时没有用到图片,因为个人来说用UI只是方便游戏,而不是为了做一个美观的界面,图片界面的制作其实就是使用CSS插入背景图片素材,并不难,如果你有兴趣,以下是本站其他玩家分享的UI框架实战教程,可以学习参考。

另外一种学习方式是运行mudlet游戏列表中的国外游戏(如:Midnight Sun 2),直接看看别人的代码学习。

京ICP备13031296号-4