继续上一篇 【cocos2dx进阶】调试篇(1)基础介绍 的内容,此次主要讲下对于Cocos2dx的一些小改造。node
先说Cocosdx关于调试的一些设计。主要包括2块内容,一个是log输出,一个是节点信息的反馈。ide
log输出函数
其实核心函数是cocos2d::CCLog直接调用的话,都会输出信息来的。这个函数提供了对平台函数的封装,有须要的同窗能够查看相关的平台代码。工具
而后,有同窗想说,个人输出须要分级,而后仅在debug下工做,因而,就有了下面这些扩展出来的宏定义post
#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能够把当前的函数名打印出来。
this
节点信息spa
Cocos2dx为了更方便的输出调试信息,增长了description函数debug
// 早期版本 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 // 结束 };
重载了ccobject中的函数
/////////////////////////// // 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的一些小改造。