你好,欢迎来到本章,我是幽白银,你可以叫我白银。由于内容太多,裙子一个人写不过来,我申请成为了教程编写人。以下是申请过程
废话不多说就你废话最多,我们现在开始本章的教学。
什么是UI?
用户界面(User Interface)是指对软件的人机交互、操作逻辑、界面美观的整体设计。好的UI设计不仅是让软件变得有个性有品味,还要让软件的操作变得舒适、简单、自由、充分体现软件的定位和特点。 ——百度百科
UI能达到什么效果呢?这里放一张UI做的界面
当然,这么复杂的效果不可能在一章教程里面就全部教会。但是别灰心,我们从头开始。
编写UIState
首先,我们要创建一个叫UI
的文件夹
然后在里面创建一个项目
我们将它命名为ExampleUI.cs
我们要使用的是Tr原生
的UI,所以我们要继承UIState
输入public override
,找到这个名为OnInitialize
的方法
我们将在这里为UI添加部件
以下代码的作用是实例化一个面板,并且将其注册到UIState
//实例化一个面板 UIPanel panel = new UIPanel(); //设置面板的宽度 panel.Width.Set(488f, 0f); //设置面板的高度 panel.Height.Set(568f, 0f); //设置面板距离屏幕最左边的距离 panel.Left.Set(-244f, 0.5f); //设置面板距离屏幕最上端的距离 panel.Top.Set(-284f, 0.5f); //将这个面板注册到UIState Append(panel);
那么,该怎么往面板上面添加一个按钮呢?请看如下代码
//用tr原版图片实例化一个图片按钮 UIImageButton button = new UIImageButton(ModContent.GetTexture("Terraria/UI/ButtonPlay")); //设置按钮距宽度 button.Width.Set(22f, 0f); //设置按钮高度 button.Height.Set(22f, 0f); //设置按钮距离所属ui部件的最左端的距离 button.Left.Set(-11f, 0.5f); //设置按钮距离所属ui部件的最顶端的距离 button.Top.Set(-11f, 0.5f); //将按钮注册入面板中,这个按钮的坐标将以面板的坐标为基础计算 panel.Append(button);
既然是按钮,那么按下应该要有效果吧?使用button.OnClick
来让按钮按下时触发事件!你可以输入button.OnClick+=
然后按下Tab键让vs帮你生成事件!
实例化按钮并注册事件的代码如下
//用tr原版图片实例化一个图片按钮 UIImageButton button = new UIImageButton(ModContent.GetTexture("Terraria/UI/ButtonPlay")); //设置按钮距宽度 button.Width.Set(22f, 0f); //设置按钮高度 button.Height.Set(22f, 0f); //设置按钮距离所属ui部件的最左端的距离 button.Left.Set(-11f, 0.5f); //设置按钮距离所属ui部件的最顶端的距离 button.Top.Set(-11f, 0.5f); //注册一个事件,这个事件将会在按钮按下时被激活 button.OnClick += Button_OnClick; //将按钮注册入面板中,这个按钮的坐标将以面板的坐标为基础计算 panel.Append(button);
如果我们想在事件按下时输出一段文字,该怎么做呢?我们可以使用Main.NewText("");
来在tr左下角输出文字!
以下是事件的代码
private void Button_OnClick(UIMouseEvent evt, UIElement listeningElement) { Main.NewText("你按下了一个按钮!"); }
然后,我们需要一个static
变量来控制UI的开关,你可以这么写public static bool Visible = false;
接下来我们可以注册一个按钮,让这个按钮按下时关闭UI。以下是注册按钮的代码
//用tr原版图片实例化一个图片按钮 UIImageButton closeButton = new UIImageButton(ModContent.GetTexture("Terraria/UI/ButtonDelete")); //设置按钮距宽度 closeButton.Width.Set(22f, 0f); //设置按钮高度 closeButton.Height.Set(22f, 0f); //设置按钮距离所属ui部件的最左端的距离 closeButton.Left.Set(-22f, 1f); //设置按钮距离所属ui部件的最顶端的距离 closeButton.Top.Set(0f, 0f); //注册一个事件,这个事件将会在按钮按下时被激活 closeButton.OnClick += CloseButton_OnClick; //将按钮注册入面板中,这个按钮的坐标将以面板的坐标为基础计算 panel.Append(closeButton);
事件的代码如下
private void CloseButton_OnClick(UIMouseEvent evt, UIElement listeningElement) { Visible = false; }
绘制UI并使UI的事件生效
我们编写了UIState,接下来,是让它生效的时候。我们来到继承Mod
类的类,创建两个变量
ExampleUI
就是我们刚刚编写的那个UIState
的子类,而UserInterface
则是用来托管UI事件的一个类。
然后来到名为Load
的方法,将它们实例化并且设置激活它们
以下是代码
//建立一个类型为ExampleUI的变量 internal ExampleUI exampleUI; //建立一个类型为UserInterface的变量 internal UserInterface exampleUserInterface; public override void Load() { //将exampleUI实例化 exampleUI = new ExampleUI(); //将exampleUI初始化 exampleUI.Activate(); //将exampleUserInterface实例化 exampleUserInterface = new UserInterface(); //让exampleUserInterface代理exampleUI的事件触发 exampleUserInterface.SetState(exampleUI); }
实例化了后,我们还需要让它运作起来,输入public override
,找到名为UpdateUI
的方法,这个方法在游戏运行时都在执行。我们可以在其中输入if (ExampleUI.Visible) exampleUserInterface?.Update(gameTime);
用以在游戏运行时让exampleUserInterface
在游戏运行时托管exampleUI
的事件
以下是代码
public override void UpdateUI(GameTime gameTime) { //当Visible为true时(当UI开启时) if (ExampleUI.Visible) //如果exampleUserInterface不是null(非空)就执行Update方法 exampleUserInterface?.Update(gameTime); base.UpdateUI(gameTime); }
最后,我们还要让UI被绘制出来,被我们看到。输入public override
找到这个名为ModifyInterfaceLayers
的方法,可以看到里面有个名为layers
的参数,这个参数包含了tr所有的绘制图层你可以在这里动点骚操作,比如RemoveAt之类的,我们将在这个集合里插入一个成员来达到绘制的目的。以下是代码
public override void ModifyInterfaceLayers(List<GameInterfaceLayer> layers) { //寻找一个名字为Vanilla: Mouse Text的绘制层,也就是绘制鼠标字体的那一层,并且返回那一层的索引 int MouseTextIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Mouse Text")); //寻找到索引时 if (MouseTextIndex != -1) { //往绘制层集合插入一个成员,第一个参数是插入的地方的索引,第二个参数是绘制层 layers.Insert(MouseTextIndex, new LegacyGameInterfaceLayer( //这里是绘制层的名字 "Test : ExampleUI", //这里是匿名方法 delegate { //当Visible开启时(当UI开启时) if (ExampleUI.Visible) //绘制UI(运行exampleUI的Draw方法) exampleUI.Draw(Main.spriteBatch); return true; }, //这里是绘制层的类型 InterfaceScaleType.UI) ); } base.ModifyInterfaceLayers(layers); }
开启UI
总算是写好了,开启UI来看看!我们来到继承ModPlayer
的类,输入public override
找到这个名为OnEnterWorld
的方法,这个方法在玩家进入世界的时候执行。在其中输入UI.ExampleUI.Visible = true;
来开启UI!以下是代码
public override void OnEnterWorld(Player player) { UI.ExampleUI.Visible = true; base.OnEnterWorld(player); }
接下来编译模组并进入世界,可以看见UI成功加载出来了!
欸Σ(っ °Д °;)っ,怎么没有???这不科学!!!
…..没保存
可以看到,UI加载出来了!
ExampleUI源码
以下是小作业
等我学会怎么布置小作业再来吧(╯‵□′)╯︵┻━┻
好,不愧是你
好,不愧是你
好,不愧是大佬
Test.OnEnterWorld(Player)’: no suitable method found to override 警告
大佬这是啥操作
请问你是写在ModPlayer吗(
那个问题倒是解决了
但是又ExampleUI’ does not contain a definition for ‘Visible了
那么请问你在ExampleUI里面写了public static bool Visible = false;了嘛?
由于我个人的原因无法加群询问,麻烦你们了
可否在GitHub内上传一下UI的成功代码?我的UI错误频出,希望能借鉴一下(P.S:TmodLoader里的ExampleMod的UI同样有Bug,他把ExampleMod的namespace用成了type)
传了,由于cs文件不支持,所以我传了zip