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的连接。

  • 相关阅读:
    打开安装 好的Microsoft Dynamics CRM 4.0 报错误为 Caller does not have enough privilege to set CallerOriginToken to the specified value 的解决办法
    基于 Windows Server 2008 的计算机对 Microsoft Dynamics CRM 4.0 的支持
    Microsoft Dynamics CRM 4.0 如何添加自定义按钮
    Microsoft Dynamics CRM 4.0 Plugin 取值,赋值,查询
    C# 中的 enum(枚举) 类型使用例子
    vue事件的绑定
    表单验证2
    node中模块
    node模块的引入
    node中的读文件
  • 原文地址:https://www.cnblogs.com/CaomaoUnity3d/p/5672384.html
Copyright © 2011-2022 走看看