笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。
CSDN视频网址:http://edu.csdn.net/lecturer/144
继续MVC代码的封装工作,上一节封装到了Control模块,我们现在很多的窗体,如何管理?这需要我们设计一个管理类去管理所有的窗体,下面给读者展示如何编写WindowManager类,代码如下:
namespace Game.View {
//场景类型 public enum EScenesType { EST_None, EST_Login, EST_Play, }
//窗体类型 public enum EWindowType { EWT_LoginWindow, //登录 EWT_UserWindow, //用户 EWT_LobbyWindow, EWT_BattleWindow, EWT_RoomWindow, EWT_HeroWindow, } public class WindowManager : Singleton<WindowManager> { public WindowManager() { mWidowDic = new Dictionary<EWindowType, BaseWindow>(); mWidowDic[EWindowType.EWT_LoginWindow] = new LoginWindow(); mWidowDic[EWindowType.EWT_UserWindow] = new UserInfoWindow(); mWidowDic[EWindowType.EWT_LobbyWindow] = new LobbyWindow(); mWidowDic[EWindowType.EWT_BattleWindow] = new BattleWindow(); mWidowDic[EWindowType.EWT_RoomWindow] = new RoomWindow(); mWidowDic[EWindowType.EWT_HeroWindow] = new HeroWindow(); } public BaseWindow GetWindow(EWindowType type) { if (mWidowDic.ContainsKey(type)) return mWidowDic[type]; return null; } public void Update(float deltaTime) { foreach (BaseWindow pWindow in mWidowDic.Values) { if (pWindow.IsVisible()) { pWindow.Update(deltaTime); } } } public void ChangeScenseToPlay(EScenesType front) { foreach (BaseWindow pWindow in mWidowDic.Values) { if (pWindow.GetScenseType() == EScenesType.EST_Play) { pWindow.Init(); if(pWindow.IsResident()) { pWindow.PreLoad(); } } else if ((pWindow.GetScenseType() == EScenesType.EST_Login) && (front == EScenesType.EST_Login)) { pWindow.Hide(); pWindow.Realse(); if (pWindow.IsResident()) { pWindow.DelayDestory(); } } } } public void ChangeScenseToLogin(EScenesType front) { foreach (BaseWindow pWindow in mWidowDic.Values) { if (front == EScenesType.EST_None && pWindow.GetScenseType() == EScenesType.EST_None) { pWindow.Init(); if (pWindow.IsResident()) { pWindow.PreLoad(); } } if (pWindow.GetScenseType() == EScenesType.EST_Login) { pWindow.Init(); if (pWindow.IsResident()) { pWindow.PreLoad(); } } else if ((pWindow.GetScenseType() == EScenesType.EST_Play) && (front == EScenesType.EST_Play)) { pWindow.Hide(); pWindow.Realse(); if (pWindow.IsResident()) { pWindow.DelayDestory(); } } } } /// <summary> /// 隐藏该类型的所有Window /// </summary> /// <param name="front"></param> public void HideAllWindow(EScenesType front) { foreach (var item in mWidowDic) { if (front == item.Value.GetScenseType()) { Debug.Log(item.Key); item.Value.Hide(); //item.Value.Realse(); } } } public void ShowWindowOfType(EWindowType type) { BaseWindow window; if(!mWidowDic.TryGetValue(type , out window)) { return; } window.Show(); } private Dictionary<EWindowType, BaseWindow> mWidowDic; } }
对窗体进行注册,显示,隐藏等操作,该函数实现了对游戏中所有窗体的管理工作。窗体之间如何切换?我们使用了状态机去编写逻辑,每个窗体都有自己的状态类,状态类也有共性,我们将其抽离出来,实现代码如下:
namespace Game.GameState { public interface IGameState { GameStateType GetStateType(); void SetStateTo(GameStateType gsType); void Enter(); GameStateType Update(float fDeltaTime); void FixedUpdate(float fixedDeltaTime); void Exit(); } }父类实现了后,LoginState的实现如下:
namespace Game.GameState { class LoginState : IGameState { GameStateType stateTo; GameObject mScenesRoot; public LoginState() { } public GameStateType GetStateType() { return GameStateType.GS_Login; } public void SetStateTo(GameStateType gs) { stateTo = gs; } public void Enter() { SetStateTo(GameStateType.GS_Continue); ResourceUnit sceneRootUnit = ResourcesManager.Instance.loadImmediate(GameConstDefine.GameLogin, ResourceType.PREFAB); mScenesRoot = GameObject.Instantiate(sceneRootUnit.Asset) as GameObject; LoginCtrl.Instance.Enter(); ResourceUnit audioClipUnit = ResourcesManager.Instance.loadImmediate(AudioDefine.PATH_UIBGSOUND, ResourceType.ASSET); AudioClip clip = audioClipUnit.Asset as AudioClip; AudioManager.Instance.PlayBgAudio(clip); EventCenter.AddListener<CEvent>(EGameEvent.eGameEvent_InputUserData, OnEvent); EventCenter.AddListener<CEvent>(EGameEvent.eGameEvent_IntoLobby, OnEvent); EventCenter.AddListener(EGameEvent.eGameEvent_SdkLogOff, SdkLogOff); } public void Exit() { EventCenter.RemoveListener<CEvent>(EGameEvent.eGameEvent_InputUserData, OnEvent); EventCenter.RemoveListener<CEvent>(EGameEvent.eGameEvent_IntoLobby, OnEvent); EventCenter.RemoveListener(EGameEvent.eGameEvent_SdkLogOff, SdkLogOff); //LoadUiResource.DestroyLoad(mUIRoot); LoginCtrl.Instance.Exit(); GameObject.DestroyImmediate(mScenesRoot); } public void FixedUpdate(float fixedDeltaTime) { } public GameStateType Update(float fDeltaTime) { return stateTo; } public void OnEvent(CEvent evt) { UIPlayMovie.PlayMovie("cg.mp4", Color.black, 2/* FullScreenMovieControlMode.Hidden*/, 3/*FullScreenMovieScalingMode.Fill*/); switch (evt.GetEventId()) { case EGameEvent.eGameEvent_InputUserData: SetStateTo(GameStateType.GS_User); break; case EGameEvent.eGameEvent_IntoLobby: GameStateManager.Instance.ChangeGameStateTo(GameStateType.GS_Lobby); break; } } } }以上是关于State状态机的类实现,代码如下:
namespace Game.GameState { class LoginState : IGameState { GameStateType stateTo; GameObject mScenesRoot; // GameObject mUIRoot; public LoginState() { } public GameStateType GetStateType() { return GameStateType.GS_Login; } public void SetStateTo(GameStateType gs) { stateTo = gs; } public void Enter() { SetStateTo(GameStateType.GS_Continue); ResourceUnit sceneRootUnit = ResourcesManager.Instance.loadImmediate(GameConstDefine.GameLogin, ResourceType.PREFAB); mScenesRoot = GameObject.Instantiate(sceneRootUnit.Asset) as GameObject; LoginCtrl.Instance.Enter(); ResourceUnit audioClipUnit = ResourcesManager.Instance.loadImmediate(AudioDefine.PATH_UIBGSOUND, ResourceType.ASSET); AudioClip clip = audioClipUnit.Asset as AudioClip; } public void Exit() { EventCenter.RemoveListener<CEvent>(EGameEvent.eGameEvent_InputUserData, OnEvent); EventCenter.RemoveListener<CEvent>(EGameEvent.eGameEvent_IntoLobby, OnEvent); //LoadUiResource.DestroyLoad(mUIRoot); LoginCtrl.Instance.Exit(); GameObject.DestroyImmediate(mScenesRoot); } public void FixedUpdate(float fixedDeltaTime) { } public GameStateType Update(float fDeltaTime) { return stateTo; } public void OnEvent(CEvent evt) { UIPlayMovie.PlayMovie("cg.mp4", Color.black, 2/* FullScreenMovieControlMode.Hidden*/, 3/*FullScreenMovieScalingMode.Fill*/); switch (evt.GetEventId()) { case EGameEvent.eGameEvent_InputUserData: SetStateTo(GameStateType.GS_User); break; case EGameEvent.eGameEvent_IntoLobby: GameStateManager.Instance.ChangeGameStateTo(GameStateType.GS_Lobby); break; } } } }在Enter函数中,使用了LoginCtrl类接口的调用。另外,我们编写的逻辑是不挂在脚本上的,资源都是动态加载的,后面会告诉读者如何使用,后面会继续给读者讲解。。。。。。
作者:jxw167 发表于2017/4/2 21:32:30 原文链接
阅读:17 评论:0 查看评论