zoukankan      html  css  js  c++  java
  • 仿LOL项目开发第七天

    仿LOL项目开发第七天

                                                                         by 草帽

    不知不觉已经写到了第七篇这种类型的博客,但是回过头看看之前写的,发现都只能我自己能看懂。

    我相信在看的童鞋云里雾里的,因为我基本上没怎么详细讲一个脚本怎么用?但是你们可以自己看下代码,很快你就知道怎么用!以后也可以用到自己的项目中。

    所以说阅读别人的代码非常重要,因为你们从中发现他们代码的优点和缺点。

    OK,废话不多说,我们继续上节课,上节课我们已经封装自己的UI框架,但是还少个没讲,可能有些童鞋也会遇到报错,怎么解决?

    在Window下新建一个UILib,然后里面新建一个脚本:

    WidgetFactory:

    using UnityEngine;
    using System.Collections.Generic;
    namespace UILib
    {
        public class WidgetFactory
        {
            /// <summary>
            /// 查找节点下所有的UI组件,缓存到字典里面
            /// </summary>
            /// <param name="trans"></param>
            /// <param name="parent"></param>
            /// <param name="dicAllUIObjects"></param>
            public static void FindAllUIObjects(Transform trans, IXUIObject parent, ref Dictionary<string, XUIObjectBase> dicAllUIObjects)
            {
                int i = 0;
                while (i < trans.childCount)
                {
                    Transform child = trans.GetChild(i);
                    XUIObjectBase component = child.GetComponent<XUIObjectBase>();
                    if (!(null != component))
                    {
                        goto IL_85;
                    }
                    if (component.GetType().GetInterface("IXUIListItem") == null)
                    {
                        if (dicAllUIObjects.ContainsKey(component.name))
                        {
                            Debug.Log(component.name);
                            Debug.LogError("m_dicId2UIObject.ContainsKey:" + WidgetFactory.GetUIObjectId(component));
                        }
                        dicAllUIObjects[component.name] = component;
                        component.Parent = parent;
                        goto IL_85;
                    }
                    else 
                    {
                        Debug.Log("fdsfd");
                    }
                IL_8F:
                    i++;
                    continue;
                IL_85:
                    WidgetFactory.FindAllUIObjects(child, parent, ref dicAllUIObjects);
                    goto IL_8F;
                }
            }
            /// <summary>
            /// 取得该组件所在的id(包含父亲节点的id)
            /// </summary>
            /// <param name="uiObject"></param>
            /// <returns></returns>
            public static string GetUIObjectId(IXUIObject uiObject)
            {
                string result;
                if (null == uiObject)
                {
                    result = string.Empty;
                }
                else
                {
                    string text = uiObject.CacheGameObject.name;
                    IXUIListItem iXUIListItem = uiObject as IXUIListItem;
                    if (iXUIListItem != null)
                    {
                        text = iXUIListItem.Id.ToString();
                    }
                    while (null != uiObject.Parent)
                    {
                        uiObject = uiObject.Parent;
                        string arg = uiObject.CacheGameObject.name;
                        iXUIListItem = (uiObject as IXUIListItem);
                        if (null != iXUIListItem)
                        {
                            arg = iXUIListItem.Id.ToString();
                        }
                        text = string.Format("{0}#{1}", arg, text);
                    }
                    result = text;
                }
                return result;
            }
        }
    }

    这个脚本主要是用来找UI的子物体用的。

    OK,我们正式进入到LoginWindow的完善。我们知道这个界面分为两块,一个是登陆,一个选择服务器。

    我们先来写登陆的逻辑。

    可以看到这个界面分为3个组件:

    1.用户名输入框

    2.密码输入框

    3.确认登陆按钮

    所以我们在LoginWindow初始化这些组件:

    然后在InitWidget()里面初始化这些定义的组件:

    这里的名字是我自己去的比如Login/UserNameInput,你们可以自己取自己的名字。

    Login是LoginWindow下面的子物体,然后UserNameInput是Login下面的子物体,我们用/来区分紫武器。

    OK,当我们点击确认登陆按钮的时候,肯定需要一个登陆事件给这个按钮,所以现在我们来写这个事件监听。

    然后我们来编写OnLoginSumbit方法,主要处理一些登陆逻辑的事情。

        public void OnLoginSumbit(GameObject go)
        {
            string username = this.m_Input_UsernameInput.value;
            string password = this.m_Input_PasswordInput.value;
            //如果用户名或者密码为空的话,就显示提示消息
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
            {
                CEvent evt = new CEvent(EGameEvent.eGameEvent_ShowMessage);
                evt.AddParam("content", StringConfigManager.GetString("MessageWindow.EMT_SureTip.LoginNullUsernameOrPassword"));
                EventCenter.SendEvent<EMessageType, Action<bool>>(evt, EMessageType.EMT_SureTip, (isOk) => 
                {
                    EventCenter.Broadcast(EGameEvent.eGameEvent_HideMessage);
                });
            }
            LoginCtrl.singleton.Login(username, password);
        }

    可以看到我们搞了一个当确定消息提示,如果用户名和密码为空的话。

    然后为了符合类的单一职责,我们把所有的逻辑放在LoginCtrl中。

    新建文件夹取名为Controller,然后在里面新建一个LoginCtrl类:(我忘记之前是不是讲过这个类,如果有讲过这个类,因为我太久之前写的,都忘记了,读者自行改过)。

    在写这个逻辑之前,我们先来想下我们登陆进去在选择服务器,所以登陆这个验证并没有进入到游戏服务器中,因为我们根本没有选择服务器,怎么能进到服务器中呢?

    所以我认为就只是网页简单的验证用户名密码,然后选择服务器之后才真正的进入到游戏服务器。

    所以这个登陆的逻辑步骤是:

    1.开启协程访问一个网站,这个网站验证用户名和密码。(所以我决定用PHP来写这个验证)

    2.如果验证通过之后,然后发送服务器列表给客户端,客户端再进入到选择服务器界面。

    3.客户端选择某个服务器,然后进入到这个游戏服务器。

    所以首先,我在网站文件夹下面新建一个check.php文件:

    这个脚本就是通过数据库连接,然后进行验证,这里我简单一点,我就直接都放回成功。因为我们只是做下测试,不用每步都详细。

    所以我这里只是简单放回一个success字符串,然后在LoginCtrl中:

     public void Login(string account, string password)
        {
            this.username = account;
            this.password = password;
            LOLGameDriver.Instance.StartCoroutine(CheckUserPass());
        }
        IEnumerator CheckUserPass()
        {
            if (string.IsNullOrEmpty(this.username) || string.IsNullOrEmpty(this.password))
            {
                yield break;
            }
            WWW www = new WWW("http://127.0.0.1/LOLGameDemo/check.php");
            bool success = false;
            for (int i = 0; i < 10; i++)
            {
                yield return new WaitForSeconds(0.5f);
                if (www.isDone)
                {
                    if (string.IsNullOrEmpty(www.error))
                    {
                        if (!string.IsNullOrEmpty(www.text))
                        {
                            if (www.text == "success")
                            {
                                //加载服务器信息
                                SystemConfig.LoadServerList();
                                success = true;
                                EventCenter.Broadcast(EGameEvent.eGameEvent_ShowSelectServerList);
                            }
                            else 
                            {
                                //登陆失败
                            }
                        }
                    }
                    else 
                    {
                        this.m_log.Error(www.error.ToString());
                    }
                    break;
                }
            }
            if (www != null)
            {
                www.Dispose();
                www = null;
            }
            //如果不成功
            if (!success)
            {
     
            }
            yield break;
        }

    不知读者注意到没有,如果登陆成功的话,我们就开始加载服务器列表。

    //加载服务器信息
    SystemConfig.LoadServerList();

    所以我们回到SystemConfig里面:

    /// <summary>
        /// 加载服务器列表
        /// </summary>
        public static void LoadServerList()
        {
            try
            {
                List<ServerInfo> servers;
                var url = GetCfgInfoUrlByName("ServerList");
                string xmlSerList = "";
                if (!string.IsNullOrEmpty(url))
                {
                    xmlSerList = DownloadMgr.Instance.DownLoadHtml(url);
                }
                servers = LoadXMLText<ServerInfo>(xmlSerList);
                if (servers.Count != 0)
                {
                    ServerList = servers;
                }
                for (int i = 0; i < ServerList.Count; i++)
                {
                    if (ServerList[i].id == LocalSetting.SelectedServer)
                    {
                        SelectedServerIndex = ServerList[i].id;
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                m_log.Error(e.ToString());
            }
        }
    

     

        /// <summary>
        /// 根据名字取得服务端配置信息Url
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string GetCfgInfoUrlByName(string name)
        {
            string result = "";
            foreach (var item in CfgInfoList)
            {
                if (item.name == name)
                {
                    result = item.url;
                    break;
                }
            }
            return result;
        }
    

    然后我们到Cfg.xml文件添加这个url=>id是1,名字是ServerList:

    <?xml version="1.0" encoding="utf-8"?>
    <root>
      <cfg>
        <id>0</id>
        <name>version</name>
        <url>http://127.0.0.1/LOLGameDemo/ServerVersion.xml</url>
      </cfg>
      <cfg>
        <id>1</id>
        <name>ServerList</name>
        <url>http://127.0.0.1/LOLGameDemo/ServerList.xml</url>
      </cfg>
    </root>

    然后我们添加4个游戏服务器,分别是电信2个(type为0),联通两个(type为1):

    <?xml version="1.0" encoding="utf-8"?>
    <root>
      <list>
        <id_i>0</id_i>
        <name_s>艾欧尼亚</name_s>
        <type_i>0</type_i>
        <flag_i>0</flag_i>
        <text_s>fe</text_s>
      </list>
      <list>
        <id_i>1</id_i>
        <name_s>战争学院</name_s>
        <type_i>0</type_i>
        <flag_i>0</flag_i>
        <text_s>csc</text_s>
      </list>
      <list>
        <id_i>2</id_i>
        <name_s>黑色玫瑰</name_s>
        <type_i>1</type_i>
        <flag_i>0</flag_i>
        <text_s>greger</text_s>
      </list>
      <list>
        <id_i>3</id_i>
        <name_s>洛克萨斯</name_s>
        <type_i>1</type_i>
        <flag_i>0</flag_i>
        <text_s>greger</text_s>
      </list>
    </root>

    所以我们回到LoginWindow中,添加该事件:

        protected override void OnAddListener()
        {
            EventCenter.AddListener(EGameEvent.eGameEvent_ShowSelectServerList, ShowSelectServer);
        }
        protected override void OnRemoveListener()
        {
            EventCenter.RemoveListener(EGameEvent.eGameEvent_ShowSelectServerList, Show);
        }

    在写ShowSelectServer方法之前,我们得先定义选择服务器界面组件:

        #region 选择服务器界面
        private UIPanel m_Panel_Select;//选择服务器界面整体Panel
        private UIButton m_Button_Select;//确认选择按钮
        private UIButton m_Button_LeftButton;
        private UIButton m_BUtton_RightButton;
        private UIButton m_Button_ServerListButton;//服务器列表按钮
        private XUIList m_List_Dianxin;
        private XUIList m_List_Wangtong;
        private XUISprite m_Sprite_IconBG;
        private XUISprite m_Sprite_ServerName;
        private XUISprite m_Sprite_Icon;
        private XUILabel m_Label_ServerName;
        private XUILabel m_Label_NetworkSpeed;//测试速度Label
        #endregion

    InitWeight:

            this.m_Button_ServerListButton = this.mRoot.FindChild("Select/Button/ServerListButton").GetComponent<UIButton>();
            this.m_Button_Select = this.mRoot.FindChild("Select/Button/SelectButton").GetComponent<UIButton>();
            this.m_Panel_Select = this.mRoot.FindChild("Select").GetComponent<UIPanel>();
            this.m_List_Dianxin = this.mRoot.FindChild("Select/ServerList/Table/Dianxin/DianxinGrid").GetComponent<XUIList>();
            this.m_List_Wangtong = this.mRoot.FindChild("Select/ServerList/Table/Wangtong/WangtongGrid").GetComponent<XUIList>();
            this.m_Sprite_IconBG = this.mRoot.FindChild("Select/Signal/IconBG").GetComponent<XUISprite>();
            this.m_Sprite_Icon = this.mRoot.FindChild("Select/Signal/IconAnim").GetComponent<XUISprite>();
            this.m_Sprite_ServerName = this.mRoot.FindChild("Select/Signal/Name/ServerNameIcon").GetComponent<XUISprite>();

    OK,初始化好界面后,我们回过头写ShowSelectServer:

    /// <summary>
        /// 显示选择服务器界面
        /// </summary>
        public void ShowSelectServer()
        {
            if (this.m_Panel_Select != null)
            {
                if (this.ShowServerList())
                {
                    //服务器列表按钮的sprite替换
                    if (this.m_bShowServerList)
                    {
                        this.m_Button_ServerListButton.normalSprite = "image 378";
                    }
                    else 
                    {
                        this.m_Button_ServerListButton.normalSprite = "image 383";
                    }
                    this.m_Panel_Select.enabled = true;
                    GameObject serverList = this.m_Panel_Select.transform.FindChild("ServerList").gameObject;
                    //serverList.
                    serverList.SetActive(this.m_bShowServerList);
                    //如果显示服务器列表面板,播放偏移动画
                    if (this.m_bShowServerList)
                    {
                        serverList.transform.localPosition = new Vector3(14, 0, 0);
                        TweenAlpha.Begin(serverList, 1, 1);
                        TweenPosition.Begin(serverList, 1, Vector3.zero);
                    }
                }
                else 
                {
                    Debug.LogError("服务器列表还没有初始化");
                }
            }
        }
    

      

     /// <summary>
        /// 显示服务器列表
        /// </summary>
        public bool ShowServerList()
        {
            if (this.m_bHasLoadedServerList)
            {
                return true;
            }
            if (SystemConfig.ServerList != null)
            {
                this.m_selectedServerId = SystemConfig.SelectedServerIndex;
                this.m_lastSelectServerId = SystemConfig.SelectedServerIndex;
                int indexDianxin = 0;
                int indexWangtong = 0;
                foreach (var serverInfo in SystemConfig.ServerList)
                {
                    IXUIListItem serverItem;
                    switch (serverInfo.type)
                    {
                        case 0:
                            if (serverInfo.flag == (int)ServerType.Recommend)
                            {
                                this.m_reDianxinServerId = serverInfo.id;
                            }
                            if (indexDianxin < this.m_List_Dianxin.Count)
                            {
                                serverItem = this.m_List_Dianxin.GetItemByIndex(indexDianxin);
                            }
                            else
                            {
                                serverItem = this.m_List_Dianxin.AddListItem();
                            }
                            if (serverItem != null)
                            {
                                serverItem.SetText("ServerName",serverInfo.name);
                                serverItem.SetVisible(true);
                                serverItem.TipParam = new TipParam
                                {
                                    Tip = serverItem.Tip
                                };
                                serverItem.Id = serverInfo.id;
                            }
                            else
                            {
                                serverItem.SetVisible(false);
                            }
                            indexDianxin++;
                            break;
                        case 1:
                            if (serverInfo.flag == (int)ServerType.Recommend)
                            {
                                this.m_reWangtongServerId = serverInfo.id;
                            }
                            if (indexWangtong < this.m_List_Wangtong.Count)
                            {
                                serverItem = this.m_List_Wangtong.GetItemByIndex(indexWangtong);
                            }
                            else
                            {
                                serverItem = this.m_List_Wangtong.AddListItem();
                            }
                            if (serverItem != null)
                            {
                                serverItem.SetText("ServerName", serverInfo.name);
                                serverItem.SetVisible(true);
                                serverItem.TipParam = new TipParam 
                                {
                                    Tip = serverItem.Tip
                                };
                                serverItem.Id = serverInfo.id;
                            }
                            else
                            {
                                serverItem.SetVisible(false);
                            }
                            indexWangtong++;
                            break;
                    }
                }
                this.m_bHasLoadedServerList = true;
                return true;
            }
            else 
            {
                return false;
            }
        }
    

      

        #region 变量定义
        private bool m_bShowServerList = false;//是否显示服务器列表
        private bool m_bHasLoadedServerList = false;//是否已经加载过服务器列表
        private int m_selectedServerId = -1;
        private int m_lastSelectServerId = SystemConfig.SelectedServerIndex;
        private int m_reDianxinServerId = -1;//电信推荐服务器id
        private int m_reWangtongServerId = -1;//网通推荐服务器idn
        #endregion

    然后在InitWeight中,让m_Button_ServerListButton监听显示服务器列表和不显示的事件监听:

    UIEventListener.Get(this.m_Button_ServerListButton.gameObject).onClick = (x) => { this.m_bShowServerList = !this.m_bShowServerList; ShowSelectServer(); };

    还有我们点击某个服务器,得把那个服务器的id,记录下来,所以我们还是注册一个事件:

    this.m_List_Dianxin.RegisterListOnClickEventHandler(new ListOnClickEventHandler(this.OnServerListItemClick));
    
    /// <summary>
        /// 服务器某个被点击
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private bool OnServerListItemClick(IXUIListItem item)
        {
            if (null == item)
            {
                return false;
            }
            this.m_selectedServerId = item.Id;
            ServerInfo info = SystemConfig.GetServerInfoById(this.m_selectedServerId);
            bool active = true;
            if (info.flag == (int)ServerType.Close || info.flag == (int)ServerType.Maintain)
            {
                active = false;
            }
            ShowServerSignal(active, info);
            return true;
        }
        /// <summary>
        /// 播放动画
        /// </summary>
        /// <param name="bActive"></param>
        /// <param name="info"></param>
        private void ShowServerSignal(bool bActive,ServerInfo info)
        {
            if (bActive)
            {
                if (info.id == 0)
                {
                    this.m_Sprite_Icon.SetSprite("image 967", "Atlas/SelectAtlas/SelectServerAtlas");
                    this.m_Sprite_ServerName.SetSprite("image 975");
                }
                else 
                {
                    this.m_Sprite_Icon.SetSprite("image 1015", "Atlas/SelectAtlas/SelectServerAtlas");
                    this.m_Sprite_ServerName.SetSprite("image 1012");
                }
                if (this.m_Sprite_IconBG != null)
                {
                    this.m_Sprite_IconBG.PlayFlash(false);
                    this.m_Sprite_ServerName.Alpha = 0f;
                    this.m_Sprite_Icon.Alpha = 0f;
                    TweenAlpha.Begin(this.m_Sprite_ServerName.gameObject, 0.8f, 1f);
                    TweenAlpha.Begin(this.m_Sprite_Icon.gameObject, 0.8f, 1f);          
                }
            }
        } 

     OK,大致就是这么多的代码,具体步骤:

    1.如果选择服务器Panel不激活的话,就显示服务器列表,然后激活。

    2.注册一些按钮的事件

    3.记录下来选择的服务器id

    然后我们点击选择按钮,就发送这个服务器id给游戏网关服务器,网关服务器就把用户连接到这个游戏服务器中。

    下节课,我们就开始进入游戏服务器连接,当然这里就涉及到NetworkManager的编写,主要是TCp的连接。

  • 相关阅读:
    红外应用
    电池分类及特点
    温湿度传感器AM2302(DH22)
    lora
    跳频扩频技术学习
    STM32F4/F7运算性能
    物联网相关模块
    DC-DC芯片
    外部引用CSS中 link与@import的区别
    超酷实用的jQuery焦点图赏析及源码
  • 原文地址:https://www.cnblogs.com/CaomaoUnity3d/p/5672384.html
Copyright © 2011-2022 走看看