仿LOL项目开发第五天
仿LOL项目开发第五天
by草帽
今天呢,我们看下能开发什么内容,首先上节我们已经讲了UI框架的搭建,上节还遗留下很多问题,比如说消息的字符是代码里面自己赋值的。
那么就比较死板,按照正常的逻辑,那些字符我们得从配置文件中获取,然后赋值给消息提示。
所以呢,我们创建一个StringConfigManager来统一管理这些字符串。
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文件夹下面:
<?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里面用上。
//根据不同的消息类型,显示不同的提示消息 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里面初始化。
void Init() { WindowManager.singleton.Init();//界面UI初始化 StringConfigManager.singleton.Init();//字符管理器初始化 }
Ok,大功告成,我们运行程序。
与之前的一模一样,但是我们现在只要改下配置文件里面的字符,程序中的字符也会改变。
OK,我们接着做,更新消息提示框,还是在MessageWindow里面,我们只需要再添加一个消息类型:EWT_UpdateTip和EWT_UpdateDownload:
然后再修改MessageWindow里面的代码:
未完待续。。。。。。
时隔几日,终于才有时间来写博客。这几日,当然我也没有闲着,也修改了好多代码。所以如果代码中有些步骤错过的话,可以留言给我。
OK,我们这几日试着发现这样的消息类型,要定到死为止,所以我定了一个总的消息类型:
/// <summary> /// 消息类型 /// </summary> public enum EMessageType { EMT_None = -1, EMT_UpdateDownload, //更新下载提示 EMT_Double, //两个按钮 EMT_Tip, //提示 EMT_SureTip //确定提示 }
确定提示:
两个按钮:
仅仅提示:
还有比较特殊的更新界面提示(其实就是double+多字符Label):
OK,已经知道了这么多的消息类型,那么我们就实现这些类型的表现:在MessageWindow的ShowMessage里面:
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:
private UIButton m_centerButton;//中间按钮
然后在InitWeight里面添加事件监听:
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);
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里面改下代码:
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()修改下参数错误:
public override void Init() { EventCenter.AddListener<CEvent,EMessageType,Action<bool>>(EGameEvent.eGameEvent_ShowMessage, ShowMessage); }
你们全部修改完成之后,我们回到LOLGameDriver修改下:
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,我们接着制作其他消息提示框,其实大致步骤是一样的:
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("数据读取中"); } }); };
我们重点看看更新消息提示框(其实也一样,那就不重点看看了):
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方法:
protected override void OnAddListener() { EventCenter.AddListener(EGameEvent.eGameEvent_HideMessage, Hide); } protected override void OnRemoveListener() { EventCenter.RemoveListener(EGameEvent.eGameEvent_HideMessage, Hide); }
然后在适当的时机调用隐藏消息提示框。
OK,我这里又要改下,在CheckVersion里面,如果不需要更新的话,就添加执行finished的委托,我忘记加了。
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,消息界面已经搞一个段落,我们下节开始登陆的逻辑编程,这里就涉及游戏状态机的管理。