仿LOL项目开发第五天

仿LOL项目开发第五天

                                      by草帽

今天呢,我们看下能开发什么内容,首先上节我们已经讲了UI框架的搭建,上节还遗留下很多问题,比如说消息的字符是代码里面自己赋值的。

那么就比较死板,按照正常的逻辑,那些字符我们得从配置文件中获取,然后赋值给消息提示。

所以呢,我们创建一个StringConfigManager来统一管理这些字符串。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using UnityEngine;
using System.Collections.Generic;
using System.Xml;
using Game;
using Utility;
/// <summary>
/// 字符串管理器
/// </summary>
public class StringConfigManager : Singleton<StringConfigManager>
{
    //所有字符缓存字典
    private Dictionary<string, string> m_oDicAllStringData;
    public StringConfigManager()
    {
        this.m_oDicAllStringData = new Dictionary<string, string>();
    }
    public void Init()
    {
        this.m_oDicAllStringData.Clear();
        XmlDocument doc = XmlResAdapter.GetXmlDocument(UnityTools.LoadFileText(SystemConfig.StringPath));
        OnLoadStringFinishedEventHandler(doc);
    }
    /// <summary>
    /// 根据字符id取得字符串内容
    /// </summary>
    /// <param name="id"></param>
    public static string GetString(string id)
    {
        return StringConfigManager.singleton.TryGetString(id);
    }
    private void OnLoadStringFinishedEventHandler(XmlDocument doc)
    {
        if (doc != null)
        {
            XmlNode root = doc.SelectSingleNode("root");
            XmlNodeList tableList = root.ChildNodes;
            foreach (var node in tableList)
            {
                XmlElement ele = (XmlElement)node;
                string id = ele.GetAttribute("id");
                string content = ele.InnerText;
                bool flag = this.m_oDicAllStringData.ContainsKey(id);
                if (flag)
                {
                    Debug.Log("字符字典已经包含该字符id");
                }
                this.m_oDicAllStringData[id] = content;
            }
        }
    }
    private string TryGetString(string id)
    {
        if (this.m_oDicAllStringData.ContainsKey(id))
        {
            return this.m_oDicAllStringData[id];
        }
        else
        {
            return id;
        }
    }
}

然后创建string.xml文件,存放在Resources/Config文件夹下面:

 

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<root>
  <ele id="MessageWindow.EMT_NetTryAgain.Title">网络错误</ele>
  <ele id="MessageWindow.EMT_NetTryAgain.Content">您的网络无法连接上服务器,请检查下网络是否良好。</ele>
  <ele id="MessageWindow.EMT_NetTryAgain.TryAgainButton">image 168</ele>
  <ele id="MessageWindow.EMT_NetTryAgain.QuitButton">image 172</ele>
</root>

更改MessageWindow里面的代码,将StringConfigManager里面用上。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//根据不同的消息类型,显示不同的提示消息
switch (this.m_eMessageType)
{
        //如果是重试消息的话
    case EMessageType.EMT_NetTryAgain:
        this.m_firstButton.normalSprite = StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.TryAgainButton");
        this.m_secondButton.normalSprite = StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.QuitButton");
        this.m_title.text = StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.Title");
        this.m_content.text = StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.Content");
        break;
    case EMessageType.EMT_ReConnect:
        break;
    case EMessageType.EMT_None:
        break;
}

对了,在用StringConfigManager之前得先初始化,那么在LOLGameDriver里面初始化。

 

1
2
3
4
5
void Init()
{
    WindowManager.singleton.Init();//界面UI初始化
    StringConfigManager.singleton.Init();//字符管理器初始化
}

Ok,大功告成,我们运行程序。

与之前的一模一样,但是我们现在只要改下配置文件里面的字符,程序中的字符也会改变。

OK,我们接着做,更新消息提示框,还是在MessageWindow里面,我们只需要再添加一个消息类型:EWT_UpdateTip和EWT_UpdateDownload:

然后再修改MessageWindow里面的代码:

未完待续。。。。。。

 时隔几日,终于才有时间来写博客。这几日,当然我也没有闲着,也修改了好多代码。所以如果代码中有些步骤错过的话,可以留言给我。

OK,我们这几日试着发现这样的消息类型,要定到死为止,所以我定了一个总的消息类型:

 

1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// 消息类型
/// </summary>
public enum EMessageType
{
    EMT_None = -1,
    EMT_UpdateDownload, //更新下载提示
    EMT_Double, //两个按钮
    EMT_Tip,     //提示
    EMT_SureTip //确定提示
}

确定提示:

两个按钮:

仅仅提示:

还有比较特殊的更新界面提示(其实就是double+多字符Label):

OK,已经知道了这么多的消息类型,那么我们就实现这些类型的表现:在MessageWindow的ShowMessage里面:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public void ShowMessage(CEvent evt,EMessageType type,Action<bool> callback = null)
   {
       //如果已经显示了,就直接返回
       if (mVisible && evt.GetParamCount() == 0)
       {
           return;
       }
       this.m_eMessageType = type;
       this.m_actCallBack = callback;
       Show();
       //根据不同的消息类型,显示不同的提示消息
       switch (this.m_eMessageType)
       {
               //如果是重试消息的话
           case EMessageType.EMT_Double:
               this.m_firstButton.gameObject.SetActive(true);
               this.m_secondButton.gameObject.SetActive(true);
               this.m_centerButton.gameObject.SetActive(false);
               this.m_firstButton.normalSprite = StringConfigManager.GetString("MessageWindow.EMT_Double.TryAgainButton");
               this.m_secondButton.normalSprite = StringConfigManager.GetString("MessageWindow.EMT_Double.QuitButton");
               this.m_title.text = evt.GetParam("title") as string;//StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.Title");
               this.m_content.text = evt.GetParam("content") as string; //StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.Content");
               break;
           case EMessageType.EMT_Tip:
               this.m_frame.spriteName = StringConfigManager.GetString("EMessageType.EMT_Tip.Frame");
               this.m_firstButton.gameObject.SetActive(false);
               this.m_secondButton.gameObject.SetActive(false);
               this.m_centerButton.gameObject.SetActive(false);
               this.m_title.gameObject.SetActive(false);
               this.m_content.alignment = NGUIText.Alignment.Center;
               this.m_content.text = evt.GetParam("content") as string;//StringConfigManager.GetString("EMessageType.EMT_UpdateTip.Content1");
               break;
           case EMessageType.EMT_SureTip:
               this.m_frame.spriteName = StringConfigManager.GetString("EMessageType.EMT_Tip.Frame");
               this.m_firstButton.gameObject.SetActive(false);
               this.m_secondButton.gameObject.SetActive(false);
               this.m_centerButton.gameObject.SetActive(true);
               this.m_title.gameObject.SetActive(false);
               this.m_content.alignment = NGUIText.Alignment.Center;
               this.m_content.text = evt.GetParam("content") as string;
               break;
           case EMessageType.EMT_UpdateDownload:
               this.m_frame.spriteName = StringConfigManager.GetString("EMessageType.EMT_UpdateTip.Frame");
               this.m_firstButton.gameObject.SetActive(true);
               this.m_secondButton.gameObject.SetActive(true);
               this.m_firstButton.normalSprite = StringConfigManager.GetString("MessageWindow.EMT_UpdateDownload.LookNewButton");
               this.m_secondButton.normalSprite = StringConfigManager.GetString("MessageWindow.EMT_Double.TryAgainButton");
               this.m_title.gameObject.SetActive(false);
               this.m_content.alignment = NGUIText.Alignment.Center;
               this.m_content.text = string.Format(StringConfigManager.GetString("EMessageType.EMT_UpdateDownload.Content"), evt.GetParam("index"), evt.GetParam("total"), evt.GetParam("fileName"));
               break;
           case EMessageType.EMT_None:
               break;
       }

因为我们消息改了,所以有些组件也需要添加进去,我们重新制作消息UI界面,我们新增一个centerButton:

 

1
private UIButton m_centerButton;//中间按钮

然后在InitWeight里面添加事件监听:

 

1
2
3
4
this.m_centerButton = this.mRoot.FindChild("Frame/CenterButton").GetComponent<UIButton>();
EventDelegate.Add(this.m_firstButton.onClick, OnFirstBtn);
EventDelegate.Add(this.m_secondButton.onClick, OnSecondBtn);
EventDelegate.Add(this.m_centerButton.onClick, OnFirstBtn);

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void OnFirstBtn()
{
    switch (this.m_eMessageType)
    {
        //如果是重试消息的话
        case EMessageType.EMT_Double:
            this.m_actCallBack(true);
            Hide();
            break;
        case EMessageType.EMT_None:
            break;
    }
}
public void OnSecondBtn()
{
    switch (this.m_eMessageType)
    {
        //如果是重试消息的话
        case EMessageType.EMT_Double:
            this.m_actCallBack(false);
                Hide();
            break;
        case EMessageType.EMT_None:
            break;
    }
} 

 

这里我只写double类型的,以后再来扩充。

可能有些童鞋发现了,那么消息的内容不是都是不一样吗,我们不能写死了,所以我们要在其他地方传入到这个方法里面赋值。

那么我们直接用EventCenter.Broadcast是不支持传递参数的,所以我们在ShowMessage传入一个Cevent类的实例,这个类主要是传递值的。也就是在两个类之间传递数值。

我已经在ShowMessage传入了Cevent类型,所以我们需要到EventCenter里面改下代码:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static public void SendEvent(CEvent evt)
{
    Broadcast<CEvent>(evt.GetEventId(), evt);
}
static public void SendEvent<T>(CEvent evt, T arg2)
{
    Broadcast<CEvent, T>(evt.GetEventId(), evt, arg2);
}
static public void SendEvent<T,U>(CEvent evt, T arg2,U arg3)
{
    Broadcast<CEvent, T, U>(evt.GetEventId(), evt, arg2,arg3);
}
static public void SendEvent<T, U,V>(CEvent evt, T arg2, U arg3,V arg4)
{
    Broadcast<CEvent, T, U,V>(evt.GetEventId(), evt, arg2, arg3,arg4);
}

 修改SendEvent方法能带更多的泛型参数。

OK,那么我们怎么使用,我们先修改下MessageWindow的错误:

到Init()修改下参数错误:

 

1
2
3
4
public override void Init()
{
    EventCenter.AddListener<CEvent,EMessageType,Action<bool>>(EGameEvent.eGameEvent_ShowMessage, ShowMessage);     
}

你们全部修改完成之后,我们回到LOLGameDriver修改下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
checkTimeout.AsynIsNetworkTimeout((result) =>
            {
                //网络良好
                if (result)
                {
                    //开始更新检测
                    DoInit();
                }
                else //说明网络错误
                {
                    Debug.Log("网络错误");
                    //开始消息提示框,重试和退出
                    CEvent evt = new CEvent(EGameEvent.eGameEvent_ShowMessage);
                    evt.AddParam("title", StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.Title"));
                    evt.AddParam("content", StringConfigManager.GetString("MessageWindow.EMT_NetTryAgain.Content"));
                    EventCenter.SendEvent<EMessageType, Action<bool>>(evt, EMessageType.EMT_Double, (isOk) =>
                    {
                        if (isOk)
                        {
                            TryInit();//重试
                        }
                        else
                        {
                            Application.Quit();//退出
                        }
                    });
                }
            });

先new一个CEvent实例,然后在其中添加两个参数,也就是我们消息的标题和内容。然后调用SendEvent方法。OK,我们在MessageWindow接收到CEvent传递的“title”和“content”两个参数的值,初始化消息框的Label的值。

OK,我们接着制作其他消息提示框,其实大致步骤是一样的:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Action<bool> fileDecompress = (finish) =>
        {
            LOLGameDriver.Invoke(() =>
            {
                EventCenter.Broadcast(EGameEvent.eGameEvent_HideMessage);
                if (finish)
                {
                    CEvent evt = new CEvent(EGameEvent.eGameEvent_ShowMessage);
                    evt.AddParam("content", StringConfigManager.GetString("EMessageType.EMT_UpdateTip.Content2"));
                    EventCenter.SendEvent<EMessageType, Action<bool>>(evt, EMessageType.EMT_Tip, null);
                    Debug.Log("正在更新本地文件");
                }
                else
                {
                    CEvent evt = new CEvent(EGameEvent.eGameEvent_ShowMessage);
                    evt.AddParam("content", StringConfigManager.GetString("EMessageType.EMT_UpdateTip.Content3"));
                    EventCenter.SendEvent<EMessageType, Action<bool>>(evt, EMessageType.EMT_Tip, null);
                    Debug.Log("数据读取中");
                }
            });
        };

 

我们重点看看更新消息提示框(其实也一样,那就不重点看看了):

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Action<int, int, string> taskProgress = (total, index, fileName) =>
{
    LOLGameDriver.Invoke(() =>
    {
        //正在下载更新文件
        Debug.Log(string.Format("正在下载更新文件({0}/{1}:{2})", index + 1, total, fileName));
        CEvent evt = new CEvent(EGameEvent.eGameEvent_ShowMessage);
        evt.AddParam("index", index + 1);
        evt.AddParam("total", total);
        evt.AddParam("fileName", fileName);
        EventCenter.SendEvent<EMessageType, Action<bool>>(evt, EMessageType.EMT_UpdateDownload, (isOk) =>
        {
            if (isOk)
            {
                Application.OpenURL("http://www.baidu.com");
            }
            else
            {
 
            }
        });
    });
};

OK,既然我们能让一个消息界面显示,那么我也需要自动让他消息,那么我们就再加个消息不显示的事件类型,在AddListener里面,直接添加WindowBase父类的Hide方法:

 

1
2
3
4
5
6
7
8
protected override void OnAddListener()
{
    EventCenter.AddListener(EGameEvent.eGameEvent_HideMessage, Hide);
}
protected override void OnRemoveListener()
{
    EventCenter.RemoveListener(EGameEvent.eGameEvent_HideMessage, Hide);
}

然后在适当的时机调用隐藏消息提示框。

OK,我这里又要改下,在CheckVersion里面,如果不需要更新的话,就添加执行finished的委托,我忘记加了。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void CheckVersion(Action<bool> fileDecompress,Action<int,int,string> taskProgress,Action<int,long,long> progress,Action finished,Action<Exception> error)
{
    BeforeCheck((result) =>
    {
        if (result)
        {
            //需要更新
            Debug.Log("需要更新");
            EventCenter.Broadcast(EGameEvent.eGameEvent_HideMessage);
            CheckAndDownload(fileDecompress, taskProgress, progress, finished, error);
        }
        else
        {
            EventCenter.Broadcast(EGameEvent.eGameEvent_HideMessage);
            //不需要更新
            Debug.Log("不需要更新");
            if (finished != null)
            {
                finished();
            }
        }
    }, () => { error(new Exception("下载版本文件超时!")); });
}

 

  

 

OK,消息界面已经搞一个段落,我们下节开始登陆的逻辑编程,这里就涉及游戏状态机的管理。

 仿LOL项目开发第六天地址链接

posted @   草帽领  阅读(1266)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法
点击右上角即可分享
微信分享提示