饥荒mod制作吧 关注:2,786贴子:11,860
  • 6回复贴,共1

联机版简单的界面(widgets/screens)教程

取消只看楼主收藏回复

基础知识:首先联机版的大部分的components和全部的sg和brain是在主机上执行的,而客户端仅有部分的含网络变量的附件(replica)和全部的界面部分(可以理解为客机从主机接受信息和自身的设置形成界面),因此,联机版复杂点的界面(客户端不含有需要完成界面所需的所有数据的)都100%的是所有人mod,否则就是客户端mod,在界面设计方面单机版和联机版应该基本无异(虽然我并没有看过单机版的界面有关的代码),不过值得注意的是很多Image的路径单机版和联机版不一样,所以不要懒得直接跨版本复制粘贴美术资源的路径,显示不出来滴~
因为有过好几个月的开多层世界服务器的经历,每次重置都需要挖洞,相当的麻烦。比如建一个10层世界,就要10个世界都跑一次,每个世界挖9个通往其他世界的洞,而如果设立一个世界作为中转站,那么那个世界的数据量会过大,经常卡成狗,或者连接人数过多经常掉线,所以是不是可以设计一个传送器?
好了进入正文了,下面的教程会教你怎么设计一个类似于打开地图的那个地图摁建,摁下这个摁建会弹出一个窗口,输入数字可以直接传送到对应世界


IP属地:北京1楼2017-07-20 09:11回复
    step1:首先找到你需要点击以打开窗口的图片(设计成摁下某个键也行,不过本贴是说关于widget的,就不教那个了)
    然后在modmain里面声明:
    Assets = {
    Asset("ATLAS", "images/hud/lr_blackhole.xml"),
    Asset("IMAGE", "images/hud/lr_blackhole.tex"),
    }
    注:将得到的png格式的图片随便找个有images文件夹的mod(没有的话自己在modmain同名目录下新建这个文件夹)在modmain的同名目录新建一个exported文件夹,然后扔进去,运行Don't Starve Together,如果你是steam的版本,并且已经安装了Don't Starve Mod Tool,那么你会在这个Images文件夹里面得到xml和tex格式的两个文件,然后把这两个文件扔到你调用的目录


    IP属地:北京2楼2017-07-20 09:21
    回复
      step2:下面用“图标”一词代表这个类似于打开地图的摁建
      首先引入新的图标,最好找个附着点,这样不要重新定位坐标,而且跟原版的界面可以更好融合在一起,代码也更加简便,所谓附着点,就是原版界面上就有的东西,那么这里我们选用原版的打开地图图标作为附着点,直接使用AddChild代码,使用此代码,图标的原点就会在parent的位置,具体代码:
      if TheNet:GetIsClient() then--判断是不是客机(前面已经提到,界面代码是客机才需要执行的)
      local function Teleport()
      end
      local function Blackhole(self)
      local ImageButton = require("widgets/imagebutton")--类似的还有AnimButton,TextButton等等,原版提供了大量这种代码,不需要自己写,只需要require
      self.blackhole = self:AddChild(ImageButton("images/hud/lr_blackhole.xml", "lr_blackhole.tex", nil, nil, nil, nil, {1,1}, {0,0}))
      --ImageButton的参数第一个是self不用写,打开widgets/imagebutton可以看到其他参数什么意思
      self.blackhole:SetScale(.33, .33, .33)--设置大小,第一个和第二个参数对应x,y方向图片大小(没有此代码情况下像素=大小)好像第三个参数没什么用?求教大神
      self.blackhole:SetPosition(-100, 0, 0)--把图片放在地图图标左边100单位位置
      self.blackhole:SetOnClick(Teleport)--点击后需要执行的函数
      end
      AddClassPostConstruct("widgets/mapcontrols", Blackhole)
      end


      IP属地:北京3楼2017-07-20 09:36
      回复
        当然,有时候你需要设计更加复杂的screen,并且这个screen需要调用更加复杂的原版没有的widget,这时候你需要在widgets下面新建文件 ,而不仅仅是AddChild了,不过这种widget代码和下面要讲的screen结构差不多,相信你能弄出来那个,复杂的widget问题就不大了


        IP属地:北京4楼2017-07-20 09:41
        回复
          step3:screen代码的书写
          首先当然是在先在screen下面新建文件,在这里我就新建lr_teleport.lua文件了,screen的书写实际上跟组件有些类似,不过这里调用的widget大部分都是require原版的了
          一步一步来:
          先弄个框架
          local Screen = require "widgets/screen"
          local Lr_teleport = Class(Screen ,function(self,owner)
          Screen._ctor(self, "Lr_teleport")--创建这个界面,Lr_teleport为screen名称
          TheInput:ClearCachedController()--让玩家不能使用摁键?
          self.owner = owner
          end)
          return Lr_teleport

          设置根基?
          self.root = self:AddChild(Widget("ROOT"))--可理解为创建屏幕的一个基础点
          self.root:SetVAnchor(ANCHOR_MIDDLE)--把整个界面的中心点设成屏幕中心点
          self.root:SetHAnchor(ANCHOR_MIDDLE)
          self.root:SetPosition(0,0,0)
          self.root:SetScaleMode(SCALEMODE_PROPORTIONAL)

          当然这里用了Widget,也需要调用local Widget = require "widgets/widget"
          往这个screen里面塞你需要的widget
          [一大堆要被调用的原版widget]

          [具体的调用过程]


          [其他的函数]

          就这样经过一番战斗,你完成了这个界面!
          最后别忘了把之前那个摁下图标后执行的函数Teleport给补上


          IP属地:北京5楼2017-07-20 10:19
          收起回复
            step4:RPC的讲解
            界面是在客户端进行操作的,而主机需要通过RPC来接受客机的消息,才能进行相关的操作
            RPC和网络变量一样,主客机都需要声明
            客机:AddModRPCHandler("allclients", "lr_teleport", function() end)
            主机:

            当你完成这些之后,screen里面的那段代码才能生效
            SendModRPCToServer(GetModRPC("allclients", "lr_teleport"), fnstr)


            IP属地:北京6楼2017-07-20 10:29
            回复
              本贴为楼主原创,希望可以帮助到各位写mod的朋友,转载请注明出处,最后让大家看看实际的效果

              署名:浪人
              qq:1377168934


              IP属地:北京7楼2017-07-20 10:38
              回复