笔者介绍:姜雪伟,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类接口的调用。另外,我们编写的逻辑是不挂在脚本上的,资源都是动态加载的,后面会告诉读者如何使用,后面会继续给读者讲解。。。。。。