根据解决方案,我们的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  = it->second;
        if(t_uires_data)
        {
            string tmp_name = t_uires_data->uiname();
            string tmp_value = 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切换的关系了。

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

 

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

 

posted on 2015-01-05 21:15  freeze86  阅读(554)  评论(0编辑  收藏  举报