繼續上一篇 【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的一些小改造。