首页 > 代码库 > CocosStdio 项目孵化记-动作卡牌游戏-系统设计-UI系统

CocosStdio 项目孵化记-动作卡牌游戏-系统设计-UI系统

根据解决方案,我们的UI是用Cocostdio的UI编辑器做的,在通过UI编辑器导出的资源是(.json文件 + 碎图)。

技术分享

 

技术分享

这样,会出来一个JSON文件 ,例如A.json,然后一堆碎图。为什么不使用大图呢!因为,我们打算Texturepacker对碎图进行打包,来做资源优化。

这样拼接界面的事,就可以有策划或者美术或者其他人做了。程序可以安心的写代码了,只需要做某些特殊功能的时候,让拼界面的人员给制定的控件做好命名。然后程序根据这些命名写程序就OK了。

其实我们更关注的是如何把这些界面有规律的调度起来。

在软件开发中,要注意一个问题叫MVC,Model-View-Control  其实我们所有的架构都是基于这个起来的。做GUI的架构我们必须做到下面几点。

1.UI资源的载入和释放

2.UI界面和逻辑功能分开。其实就是一遍进行资源的制作,一遍程序写功能。然后通过中间一层代码,将有关系的两者联系到一起。做到代码和逻辑的分离。

3.UI的调度问题,在上一篇文章中已经提及到了。

 

好 ,就以上3个问题,我们展开设计。按照一般的设计思路,我们首先做了一个单例类 CGuiMgr

不懂单例的同学,可以去查一下设计模式---单例是什么?

class CGuiMgr{protected:	CGuiMgr();	~CGuiMgr();	static CGuiMgr m_Inst;public:	static CGuiMgr* GetInst();	void init();	CGuiUnit* CreateGui(const char* _name);	CGuiUnit* GetGui(const char* _name,bool _create = true);	void DelGui(const char* _name);	void RegisterGui(CGuiUnit* _gui);	void update(float _fTime);protected:	typedef std::map<string, CGuiUnit*> GUIPOOL;	GUIPOOL m_GuiPool;	typedef std::map<string, string> GUIRESTABLE;	GUIRESTABLE m_GuiResTable;};

  

通过单例类CGuiMgr 来控制它的基本元素CGuiUnit ( 下面只是部分代码 只拾取了关键部分)

//每个GUI 封装一个GUI节点 用于对应资源文件 class CGuiUnit :public TouchGroup  //TouchGroup 继承了CCLayer,它可以接受消息的哦,{	friend class CGuiMgr;protected:	CGuiUnit(const char* _name,const char* _resname);	~CGuiUnit();public:	static CGuiUnit* CreateInLua(const char* _name,const char* _resname);	virtual void onEnter();	virtual void onExit();	virtual bool Load();	virtual bool UnLoad();	void setResFile(const char* _file);	const char* getName();	void select_callback(unsigned int _colorID);     //精确拾取	virtual void AdapteScreen();             //屏幕适配	void run(float fTime);protected:	void _bind();	void _unbind();	bool isLoad;	string m_Name;      //配表配置的名称,也是唯一一个名称,相当于Key 这个相当重要了,所有的关联真的都要靠key的	string m_ResFileName;  //资源文件名称	Layout* m_pLayerout;	//对应从Res文件中导出的节点	bool m_bAdapted;	CGuiActionQueue* m_pActQue;  //顺序动画,这个很重要哦};

  我们只需要从中关注的一个问题,就是CGuiMgr 去管理CGuiUnit。然后每一个CGuiUnit对应一个编辑器导出的文件。当然我们会给每一个界面起一个名称(字符串)。当然,这些关系都会写到配表当中,由策划来填写。

注意:

  在CGuiMgr上有一个函数叫做 void RegisterGui(CGuiUnit* _gui); 这个函数辅助将GuiUnit的基本元素注册到管理类中。

CGuiUnit::CGuiUnit(const char* _name,const char* _resname):isLoad(false),m_Name(_name),m_pLayerout(NULL),m_ResFileName(_resname),m_bAdapted(false),m_pActQue(NULL){    m_pActQue = new CGuiActionQueue;    init();    CGuiMgr::GetInst()->RegisterGui(this);}

也就是CGuiUnit在构造的过程中,会自动注册。这样每一个CGuiUnit对象都不会丢失的。

//CGuiMgr CGuiMgr::m_Inst;CGuiMgr* CGuiMgr::GetInst(){    return &m_Inst;}CGuiMgr::CGuiMgr(){}CGuiMgr::~CGuiMgr(){}void CGuiMgr::init()  //解析配表{    typedef map<int,TD_UIRes*> UIRESPool;    UIRESPool::iterator it = CCltBaseDataTbl::Inst()->m_mapUIRes.begin();    while( it!=CCltBaseDataTbl::Inst()->m_mapUIRes.end() )    {        TD_UIRes* t_uires_data  = http://www.mamicode.com/it->second;        if(t_uires_data)        {            string tmp_name = t_uires_data->uiname();            string tmp_value = http://www.mamicode.com/t_uires_data->resname();            m_GuiResTable[tmp_name] = tmp_value;        }        it++;    }    CREATE_GUI(CGuiJingQian);  //这个宏有点意思 。。。。。。。。    CREATE_GUI(CGuiErrorMessage);}CGuiUnit* CGuiMgr::CreateGui(const char* _name){    return GetGui(_name,true);}CGuiUnit* CGuiMgr::GetGui(const char* _name,bool _create)  //保证给你一个UI对象,但是_create 设置成true{    GUIPOOL::iterator it = m_GuiPool.find(_name);    if(it!=m_GuiPool.end())        return it->second;    if(_create)     {        GUIRESTABLE::iterator it_res = m_GuiResTable.find(_name);        if( it_res!=m_GuiResTable.end() )        {            CGuiUnit* gui = new CGuiUnit(_name,it_res->second.c_str());            gui->Load();            return gui;        }    }    return NULL;}void CGuiMgr::RegisterGui(CGuiUnit* _gui)  //注册回来,用于管理{    if(_gui)        m_GuiPool[_gui->getName()] = _gui;}void CGuiMgr::DelGui(const char* _name){    GUIPOOL::iterator it = m_GuiPool.find(_name);    if(it!=m_GuiPool.end())    {        if (it->second != NULL)            it->second->release();        m_GuiPool.erase(it);    }}void CGuiMgr::update(float _fTime)  //所有UI都给你一个更新的机会,用不用就看你自己的了{    GUIPOOL::iterator iter = m_GuiPool.begin();    for (;iter != m_GuiPool.end();++iter)    {        if (iter->second == NULL)            continue;                iter->second->run(_fTime);    }}

管理类CGuiMgr重要的实现:

  init() 初始化函数,主要是解析配表,将资源的对应关系解析出来。并存在当管理类当中的Map数据结构中。

  CreateGui() 和GetGui() 其实就是来创建一个CGuiUnit的基本对象的,其中GetGui()函数当中有一个参数 叫_create,它的意思就是,通过这个借口是否一定会拿到一个对象。如果是真,表示我一定要获得我想要的CGuiUnit对象,如果内存当中没有此对象,则创建一个新的。

  其实我们在写的时候,这个都会设置成True,如果在一些判断语句,就要设置成False了。这样,我们就保证了,在内存中同一个名称的GuiUnit对象只有一个,也就一个UI只有一个对象,剩下的就是UI切换的关系了。

  我们还是看看那个宏吧!!!

 

下面的博客 我给它取个名称 叫做 项目孵化记录 哈哈 有点意思吧!

 

CocosStdio 项目孵化记-动作卡牌游戏-系统设计-UI系统