继续上一篇 【cocos2dx进阶】调试篇(1)基础介绍 的内容,这次主要讲下对于Cocos2dx的一些小改造。
先说Cocosdx关于调试的一些设计。主要包括2块内容,一个是log输出,一个是节点信息的反馈。
log输出
其实核心函数是cocos2d::CCLog直接调用的话,都会输出信息来的。这个函数提供了对平台函数的封装,有需要的同学可以查看相关的平台代码。
然后,有同学想说,我的输出需要分级,然后仅在debug下工作,于是,就有了下面这些扩展出来的宏定义
#define __CCLOGWITHFUNCTION(s, ...) \
CCLog("%s : %s",__FUNCTION__, CCString::createWithFormat(s, ##__VA_ARGS__)->getCString())
// cocos2d debug
#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
#define CCLOG(...)
#define CCLOGINFO(...)
#define CCLOGERROR(...)
#define CCLOGWARN(...)
#elif COCOS2D_DEBUG == 1
#define CCLOG(format, ...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGERROR(format,...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGINFO(format,...) do {} while (0)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#elif COCOS2D_DEBUG > 1
#define CCLOG(format, ...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGERROR(format,...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGINFO(format,...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#endif // COCOS2D_DEBUG
__CCLOGWITHFUNCTION可以把当前的函数名打印出来。
节点信息
Cocos2dx为了更方便的输出调试信息,增加了description函数
// 早期版本
char * description();
// 3.0 beta
virtual std::string getDescription() const;
配合上面的输出函数,可以很方便的显示相关信息
又到了吐槽环节,先来说说信息输出的函数
早期的版本,返回char*,但是引入了内存泄露,虽然是调试信息,但是总有点那啥不是。
description函数不是继承的,有些类有,有些没有,于是,好尴尬。3.0以后改了,终于那啥了。
description还是只有ccnode的继承链上才能用,有点限制啊,其他地方得自己动手了。
输出函数,没啥大问题,但是输出依赖DEBUG定义,加了输出看不到才发现debug宏定义不正确。
好了,不说了。开始动手改造吧。
我们知道,Cocos2dx里面最底层的是ccobject,为了更好的调试,我们就从这里入手了
在ccobject类中添加函数:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
public:
// 输出函数
virtual void Dump(){}
protected:
// 格式化输出信息
virtual std::string dumpInfo(){return std::string();}
#endif
调用Dump,用于输出调试内容
dumpInfo用于Dump内部获取需要显示的信息
于是,我们就有了统一的调试函数Dump和用于格式化输出的dumpInfo。这个有啥用,不就是2个函数定义么,好吧,那我来举个例子。
就那输出节点信息来讲吧,可以参考老G的http://4137613.blog.51cto.com/4127613/1350243
要实现这个功能,其实可以
///////////////////////////
// ccnode.h
///////////////////////////
class CC_DLL CCNode : public CCObject
{
// 略过其他,在类最下面添加
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
public:
virtual void Dump();
protected:
void dump(int);
virtual std::string dumpInfo();
#endif
// 结束
};
///////////////////////////
// ccnode.cpp
///////////////////////////
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
void CCNode::Dump()
{
CCLog("==================== dump ====================");
dump(0);
CCLog("==============================================");
}
std::string CCNode::dumpInfo()
{
std::stringstream ss;
ss <<"[type]" <<typeid(this).name()
<<" [tag]" <<getTag()
<<" [visible]" <<getIsVisible()
<<" [postion]" <<getPositionX()<<","<<getPositionY();
return ss.str();
}
void CCNode::dump( int index)
{
std::string info(dumpInfo());
std::string strStruct;
for(int i=0;i<index;++i)
strStruct+="| ";
strStruct+="+ - ";
CCLog("%s%s",strStruct.c_str(),info.c_str());
if(m_pChildren && m_pChildren->count() > 0)
{
// draw children zOrder < 0
ccArray *arrayData = m_pChildren->data;
for(int i=0 ; i < arrayData->num; i++ )
{
CCNode* pNode = (CCNode*) arrayData->arr[i];
if ( pNode)
{
pNode->dump(index +1);
}
}
}
}
#endif
补充说明下:
dump(
int
)函数是用来递归调用的,index表示深度
typeid 是操作符,用于获知一个变量的具体类型。VS编译shi时需要启用运行时类型信息和C++异常
如果不满意ccnode通用的输出内容,可以通过重载dumpInfo,定制输出内容
再来个有用的例子。
触控操作是现在手机游戏的主流方式。cocos2dx中也实现2种方式 targeted(单点)和standard(多点)。通过注册handler方式,可以方便的监听触控事件。
设计很好,但是现实总是有点小麻烦,代码一复杂之后,常常是触摸了之后,函数没有响应到,为啥,代码没有错啊,跟下吧,进入了CCTouchDispatcher.cpp之后,一阵头晕眼花,天啊,救命……
这时候,救星来了,
//////////////////////
// CCTouchDispatcher.h
// CCTouchDispatcher类添加调试的重载函数
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
virtual void Dump();
#endif
实现
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
void CCTouchDispatcher::Dump()
{
CCLog("========= dump for CCTouchDispatcher =========");
// optimization to prevent a mutable copy when it is not necessary
unsigned int uTargetedHandlersCount = m_pTargetedHandlers->count();
unsigned int uStandardHandlersCount = m_pStandardHandlers->count();
CCLog("TargetedHandlersCount=%d",uTargetedHandlersCount);
CCLog("StandardHandlersCount=%d",uStandardHandlersCount);
//
// process the target handlers 1st
//
if (uTargetedHandlersCount > 0)
{
CCLog("========= Targeted Handlers");
CCTargetedTouchHandler *pHandler;
CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator arrayIter;
for (arrayIter = m_pTargetedHandlers->begin(); arrayIter != m_pTargetedHandlers->end(); ++arrayIter)
{
pHandler = (CCTargetedTouchHandler *)(*arrayIter);
if (! pHandler)
break;
CCLog("[%d]%s,SwallowsTouches=%d",pHandler->getPriority(),typeid(*(pHandler->getDelegate())).name(),pHandler->isSwallowsTouches());
}
}
//
// process standard handlers 2nd
//
if (uStandardHandlersCount > 0 )
{
CCLog("========= Standard Handlers");
CCMutableArray<CCTouchHandler*>::CCMutableArrayIterator iter;
CCStandardTouchHandler *pHandler;
for (iter = m_pStandardHandlers->begin(); iter != m_pStandardHandlers->end(); ++iter)
{
pHandler = (CCStandardTouchHandler*)(*iter);
if (! pHandler)
{
break;
}
CCLog("[%d]%s",pHandler->getPriority(),typeid(*(pHandler->getDelegate())).name());
}
}
CCLog("==============================================");
}
#endif
调用方式,在任何你需要的地方
cocos2d::CCTouchDispatcher::sharedDispatcher()->Dump();
效果如下:
好了,剩下的,就靠大家自己发挥了。下次,是对CCLOG的一些小改造。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。