仿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,消息界面已经搞一个段落,我们下节开始登陆的逻辑编程,这里就涉及游戏状态机的管理。

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

仿LOL项目开发第五天的更多相关文章

  1. 仿LOL项目开发第四天

    ---恢复内容开始--- 仿LOL项目开发第四天 by草帽 上节讲了几乎所有的更新版本的逻辑,那么这节课我们来补充界面框架的搭建的讲解. 我们知道游戏中的每个界面都有自己的一个类型:比如登陆界面,创建 ...

  2. 仿LOL项目开发第九天

    仿LOL项目开发第九天 by 草帽 OK,今天我们完全换了一种风格,抛弃了Unity3d的c#语法,我们来写写java的项目. 说到java服务器,当然有些人可能鄙视java的服务器速度太慢,但是相对 ...

  3. 仿LOL项目开发第八天

    仿LOL项目开发第八天 by 草帽 这节我们继续上节所讲的内容,上节我们初始化好了LoginWindow,当我们点击确认选择服务器按钮的时候,就发送服务器id给游戏服务器. 这里就开始涉及到客户端需要 ...

  4. 仿LOL项目开发第七天

    仿LOL项目开发第七天 by 草帽 不知不觉已经写到了第七篇这种类型的博客,但是回过头看看之前写的,发现都只能我自己能看懂. 我相信在看的童鞋云里雾里的,因为我基本上没怎么详细讲一个脚本怎么用?但是你 ...

  5. 仿LOL项目开发第六天

    仿LOL项目开发第六天 by草帽 OK,因为更新模块已经处理好了,接着开始登陆的编写.那么我们就需要状态机的管理. 所谓状态机就是在哪个状态执行那个状态的代码逻辑: 那么我们开始编写GameState ...

  6. 仿LOL项目开发第三天

    仿LOL项目开发第二天 by草帽 昨个我们已经实现了下载功能,但是发现没有,下载的包是压缩的,没有解压开,那么Unity是识别不了的. 所以今个我们来讲讲如何实现解压文件. 还记得吗,我们在Downl ...

  7. 仿LOL项目开发第二天

    仿LOL项目开发第二天 by草帽 接着上节来讲,上节更新还没开始写代码逻辑,今天我们补充完整. 我们找到VersionManager脚本里面的CheckVersion方法: 首先我们想到检测版本,需要 ...

  8. 仿LOL项目开发第一天

    ---恢复内容开始--- 仿LOL项目开发第一天 by---草帽 项目源码研究群:539117825 最近看了一个类似LOL的源码,颇有心得,所以今天呢,我们就来自己开发一个类似于LOL的游戏demo ...

  9. 基于Vue的WebApp项目开发(五)

    实现图片分享列表 步骤一:新增图片列表文件photolist.vue <template> <div id="tml"> 图片分享页面 </div&g ...

随机推荐

  1. ASPLOS'17论文导读——SC-DCNN: Highly-Scalable Deep Convolutional Neural Network using Stochastic Computing

    今年去参加了ASPLOS 2017大会,这个会议总体来说我感觉偏系统和偏软一点,涉及硬件的相对少一些,对我这个喜欢算法以及硬件架构的菜鸟来说并不算非常契合.中间记录了几篇相对比较有趣的paper,今天 ...

  2. 字符串匹配的KMP算法(如何实现还需静下心来细看)

    第一部分:KMP算法的理解(转:http://kb.cnblogs.com/page/176818/) 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB AB ...

  3. google的面试题(三维动态规划的范例)——(87)Scramble String

    转:http://www.cnblogs.com/easonliu/p/3696135.html 分析:这个问题是google的面试题.由于一个字符串有很多种二叉表示法,貌似很难判断两个字符串是否可以 ...

  4. 初窥Linux 之 最常用20条命令

    玩过Linux的人都会知道,Linux中的命令的确是非常多,但是玩过Linux的人也从来不会因为Linux的命令如此之多而烦恼,因为我们只需要掌握我们最常用的命令就可以了.当然你也可以在使用时去找一下 ...

  5. Android学习笔记(四) 定时器Timer

    Android考虑到线程安全问题,不允许在线程中执行UI线程. 所以在线程中不允许有UI操作 可以利用Handler机制来接收Timer每隔一秒发出的信息,也可以直接利用handler机制的 1.方法 ...

  6. 关于Android不同系统版本的市场占比情况详解

    一,google官方统计的不同Android版本市场的占比强开 google统计的数据情况 这个是google官方对于不同版本的市场占比情况.这个是针对全世界所有的Android手机占比情况. 二,友 ...

  7. awk书上练习

    文件car: plym fury chevy malibu ford mustang volvo s80 ford thundbd chevy malibu bmw 325i honda accord ...

  8. linux关闭地址空间随机化(ASLR)

    转:http://www.xuebuyuan.com/1571079.html 确认ASLR是否已经被打开,"2"表示已经打开 shanks@shanks-ubuntu:/home ...

  9. .htaccess文件

    前言 看了几篇文章,发现自己对于如何维护普通的服务器安全完全不会,先从简单的.htaccess来研究吧 .htaccess文件的作用,就是更改httpd.ini文件中的配置,但作用范围仅限当前文件夹 ...

  10. HDU 6182 A Math Problem

    暴力. $k$的$k$次方在$k=15$的时候,达到了最大不爆掉的情况. #include<bits/stdc++.h> using namespace std; long long an ...