原文出處:http://www.yxkfw.com/?p=15346
1. CCMoveTo動作運行多次,位置會發生詭異的變化,比如變成目標位置的幾倍。解決辦法,確保每次CCMoveTo之前停止之前的動作。
2. 在onEnter()函數中,忘記調用父類的onEnter()函數會導致動畫等無效。還有在init()函數中,謹記要對父類進行初始化。
3. addChild(CCNode* child, int zOrder); zOrder的值越大,顯示的位置越靠前。
4. 兩個常用命名空間宏:
#define USING_NS_CC using namespace cocos2d#define USING_NS_CC_EXT using namespace cocos2d::extension
Cocos2d-x提供的日誌輸出函數:CCLOG
5. CC_BREAK_IF:
#define CC_BREAK_IF(cond) if(cond) break
6. 關於do…while(0)或do…while(false)語句的一些特殊作用:
(1)提高代碼健壯性。
情況一,代碼執行中提前退出函數,不執行循環體中後面的部分代碼,轉而直接執行循環體外後面的代碼,當然用goto語句也可以實現這一目的。
some code…do{CC_BREAK_IF( 如果出錯,跳出while循環);//…另一些語句,如果跳出循環後,這些語句將不會執行,從而執行循環體外後面的代碼} while(0);some code…
(2)用於宏定義,#define MARCRO(para) do{macro content}while(0)的格式,原因如下:
a、避免空的宏定義產生warning,如:#define fun() do{}while(0);
b、存在一個獨立的block,可用來進行變量定義,進行復雜實現;
c、如果出現在判斷語句過後的宏,用do{}while(0)包起來可以保證宏作爲一個整體來實現,如:
#define fun() /fun1(); /fun2();if( cond == true)fun();
在上面情況使用以上宏,就會導致fun1()和fun2()不會被同時執行的情況,不符合預期目的。
d、以上情況使用單獨的{}包括宏也可以實現預期目的,但是爲什麼一定要用do{}while(0)?
#define swap(x, y) {int tmp; tmp = x; x = y; y = tmp; }if(x > y)swap(x, y);elseotherfun();
以上代碼會因爲多出一個分號報錯。 而使用do{}while(0)語句包起來,成爲一個獨立的語法單元,避免與上下文混淆。而且絕大多數編譯器都能識別do{}while(0)這種無用的循環並進行優化,所以這樣使用不會導致程序的性能降低。當然,養成在每個判斷語句後加上{}的習慣也能解決該問題。但是,在設計library的時候,不能指望library的使用者會有這種代碼規範習慣,要提高程序的健壯性,避免編譯出錯。
7.C++中單例的實現
classDataManager{private:DataManager(); //構造函數定義爲私有,防止外部調用~DataManager();public:staticDataManager* instance();staticvoiddestroyInstance();}DataManager::DataManager(){}DataManager::~DataManager(){}staticDataManager* gDataManager = NULL;DataManager* DataManager::instance() {if(!gDataManager) {gDataManager = newDataManager();}returngDataManager;}voidDataManager::destroyInstance(){if(gDataManager) {deletegDataManager;gDataManager = NULL;}}
//情況一:CCArray* strArray = CCArray::createWithCapacity(0);CCPoolManager::sharedPoolManager()->push(); //壓入一個自動回收池到回收池棧的頂端,autorelease對象僅會添加到頂端的池中for(inti = 0; i < 1000; i ++) {CCString* str = CCString::createWithFormat(“%d”,i);strArray->addObject(str);}CCPoolManager::sharedPoolManager()->pop(); //頂層的回收池釋放,內部所有對象被釋放一次,此後出現的autorelease對象則添加都下一個池中//情況二:CCArray* strArray = CCArray::createWithCapacity(0);for(inti = 0; i < 100000000; i ++) {CCPoolManager::sharedPoolManager()->push();CCString* str = CCString::createWithFormat(“%d”,i);strArray->addObject(str);CCPoolManager::sharedPoolManager()->pop();}
一般函數的返回值都用autorelease對象。
9、跟Objectiv-C的屬性對象賦值一樣,Cocos2d-x的set方法賦值也要注意內存的管理
voidAClass::setObject(CCObject* pObj){this->object->autorelease();pObj->retain();this->object = pObj;}voidAClass::setObject(CCObject* pObj){if(this->object != pObj) {this->object->release();pObj->retain();this->object = pObj;}}
10、一些內存管理的宏:
- CC_SAFE_DELETE(p) //delete一個C++對象p,如果p爲NULL則不操作,下同
- CC_SAFE_DELETE_ARRAY(p) //delete[]一個C++數組p
- CC_SAFE_FREE(p)
- CC_SAFE_RELEASE(p)
- CC_SAFE_RELEASE_NULL(p)
- CC_SAFE_RETAIN(p)
11、Cocos2d-x提供了一套類似Objective-C語言的容器類,CCArray、CCDictionary,用法也基本跟Objective-c的NSMutableArray,NSMutableDictionary一樣。還提供了CCARRAY_FOREACH(__array__, __object__)函數方便遍歷CCArray.
12、導演、場景、層、精靈、紋理:導演是控制遊戲流程的主要組件,遊戲流程控制通過在場景間的切換實現,通常,場景包含層,層包含精靈,場景與層是其他遊戲元素的容器,層處理觸摸事件、加速度計事件、鍵盤輸入事件,而精靈是展示給玩家的圖形,紋理是圖片。
節點和渲染樹:一切可以顯示的遊戲元素都是渲染樹的節點。
動作:作用於遊戲元素,規定了遊戲元素運動的方式。幀動畫是作用於精靈的一種特殊動作。
13、Cocos2d-x中存在兩種座標系,一種是繪圖座標系,與OpenGL採用的座標系相同,以左下角爲原點,向右爲x軸正向,向上爲y軸正向;另外一種座標系是紋理座標系,紋理座標系以左上角爲座標原點,向右爲x軸正向,向下爲y軸正向,只有從紋理中截取部分矩形時才使用這個座標系。
14、錨點AnchorPoint用於設置一個描點,取值爲0到1之間的實數,表示錨點相對於節點長寬的位置。錨點(0,0)表示錨點在節點左下角,(1,1)表示錨點在節點右上角
15、定時器事件:(1)CCNode的update()方法,每幀都會調用 (2)CCNode的schedule()方法
16、onEnter() 當此節點所在場景即將呈現時,會調用此方法。
- onEnterTransitionDidFinish() 當此節點所在場景的入場動作結束後,會調用此方法。如果所在場景沒有入場動作,則此方法會緊接着onEnter()後被調用
- onExit()當此節點所在場景即將退出時調用
- onExitTranshitionDidStart() 當此節點所在的出場動作結束後會調用此方法。如果所在場景沒有出場動作,則此方法會緊接着onExit()後被調用。
17、特殊的CCLayer:
- CCLayerColor:帶背景色的層
- CCLayerGradient:能設置兩種漸變色的層
- CCMenu:遊戲菜單,分爲菜單項和菜單本身,CCMenuItem是一個菜單項,相當於一個按鈕。