Cocos2d-x使用過程中遇到的錯誤(VS下開發,移植到Android釋出)(更新ing)
環境:windows7, VS2010, cocos2d-1.0.1-x-0.12.0, cygwin, eclipse, android sdk4.0.3, ndk r7b
在vs上開發,然後移植到android上.
20120718
CCArray的foreach操作:
cocos2d-x 本地通知呼叫的問題 CCNotificationCenter
在註冊的postNotification訊息函式中,不能再呼叫addObserver,可能會引發儲存CCNotificationObserver物件的CCArray擴容,導致CCArray重新new了一塊記憶體地址,CCArray首指標改變,當執行完返回postNotification函式的時候和原來的CCArray首指標不一致,導致記憶體讀取出錯。
observer->performSelector
就是註冊的訊息回撥函式。該函式內不能對再新增或減少自定義訊息。
void CCNotificationCenter::postNotification(const char *name, CCObject *object) { CCObject* obj = NULL; CCARRAY_FOREACH(m_observers, obj) { CCNotificationObserver* observer = (CCNotificationObserver*) obj; if (!observer) continue; if (!strcmp(name,observer->getName())) observer->performSelector(object); } }
20120719
強制型別轉換:
自定義類MainScene繼承自CCLayer,使用手法同HelloWorld,MainScene::scene()直接new了一個scene物件,並將MainScene的物件掛到scene下。
但是後來呼叫的時候產生錯誤操作:MainScene* pScene = (MainScene*)(pDirector->getRunningScene());scene被強制轉換成CCLayer,對所謂的MainScene物件成員操作,導致記憶體塊異常,現象就是在莫名其妙的地方掛掉,每次都不同,記憶體塊檢測也報過異常。
危險的強制記憶體轉換,切記切記!
20120723
最好不要寫出全域性變數初始化順序有依賴關係的程式碼。
const CCSize WIN_SIZE = CCDirector::sharedDirector()->getWinSize();
一開始在VS上除錯沒事,移植到Android上,初始化的時候就掛了。
查了一下資料,原因是初始化順序的問題。(具體初始化的順序沒搞清楚,⊙﹏⊙b汗,歡迎補充,感激不盡)
PS:找到了幾篇初始化靜態常量順序的文章
int get_a()
{
static int a = 5;
return a;
}
int get_b()
{
static int b = get_a();
return b;
}
20120726
playEffect
音效播放前要先preloadEffect,否則第一次播放音效沒有聲音。可以一次preloadEffect所有音效,android那邊呼叫的是HashMap儲存音效存放路徑。
vs端不寫preloadEffect也能正常播放,但是android端必須先preloadEffect才能正常播放,否則第一次播放沒有聲音。背景音樂沒發現這個問題。
20120803
CCTargetedTouchDelegate 的繼承 和 dynamic_cast
想寫個可以響應touch的sprite
類定義成了這個樣子:
class GemBoard : public CCSprite, CCTargetedTouchDelegate
然後註冊touch訊息的時候
CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true);
在這掛了,查了一下午,掛在了
-addTargetedDelegate
-CCTargetedTouchHandler::handlerWithDelegate
-initWithDelegate
-CCTouchHandler::initWithDelegate
-dynamic_cast<CCObject*>(pDelegate)->retain();
-void CCObject::retain(void)
跟到這裡,編譯器告訴我CCObject的this指標是0,我暈呀。感覺太詭異了。
原因:CCTargetedTouchDelegate在上面的寫法中是私有繼承,而根據dynamic_cast的作用:(運算子可以在執行期決定真正的型別。如果downcast是安全的(也就說,如果基類指標或者引用確實指向一個派生類物件)這個運算子會傳回適當轉型過的指標。如果downcast不安全,這個運算子會傳回空指標(也就是說,基類指標或者引用沒有指向一個派生類物件)。)上面的情況就合情合理了。
今天學到了2個知識點:
1. class B: public A, C 這種情況下A是public繼承,C是private繼承;class B: A 這個A也是private繼承
2.dynamic_cast 除了public 的其他都返回null
所以改成
class GemBoard : public CCSprite, public CCTargetedTouchDelegate
就正確了。發現自己的c++基礎真爛。
20121101
今天不是萬聖節嗎,怎麼變成了愚人節!!!
因為做的專案是VC++下開發,然後編成原生代碼在Android上執行,所以有些地方需要上真機列印log除錯。我日哦,我在程式碼里加了N多的log程式碼,就是一句也不打出來,在log上糾結了一天,一開始以為是cocos2d的程式碼出問題了,難道是自動遮蔽了log輸出?上網查資料,當然什麼也找不到。我就在加log程式碼,然後上真機,看不到log,然後繼續加log程式碼,往復迴圈。下班的時候,同事看我這麼糾結,就問我,vc上打斷點看程式執行到log程式碼處了嗎?結果是程式正常執行,斷點根本不走,靠!原來我一直在一段廢程式碼上加log!我的生命呀,就這樣浪費了。我想起了一首神曲,有興趣的同學可以聽一下:Wrong hole - DJ Lubel
20121103
CCTexture2D::initWithData
bool CCTexture2D::initWithData(const void *data, CCTexture2DPixelFormat pixelFormat, unsigned int pixelsWide, unsigned int pixelsHigh,const CCSize& contentSize)
使用資料建立紋理,我試了無數遍,各種問題都考慮了,就是不知道為啥正常創建出來的紋理顯示不出來。最後發現是contentSize這個最後的引數,我給的是(0,0)當然建立不出來了,一開始還以為是CCTexture2D建立成功後返回給我的生成的紋理大小。事實證明是我想多了……這個引數就是一開始指定要建立紋理的大小的。
20131220
runAction & OnEnter
今天學會了一個打開卷軸的動畫
一開始自己想的辦法是使用CCProgressTimer的CCProgressTo來執行這個動畫,但是因為我做的不僅是單個sprite,還有掛在上面的Label,CCProgressTimer在繪製的時候不會處理它的子節點,後來想到一個辦法,使用CCRenderTexture,將卷軸上的東西都畫到上面,然後使用CCRenderTexture生成CCProgressTimer的sprite,效果達到要求。
但是CCRenderTexture向來是不推薦使用的,因為繪製效率低,而且遊戲掛起後返回會丟失CCRenderTexture的資源。
找大能諮詢,推薦使用CCClippingNode,設定它的Stencil,然後對這個Stencil做處理就能出展示的效果。
遇到個問題:我在addChild之後替換了Stencil,然後再用這個Stencil播放動畫,死活播不出來,其他的都能播放動畫。後來發現是在節點的OnEnter之後改變節點下的子,再針對這個子的所有事件都不會發生。因為子的OnEnter函式不會再執行了。
20130901
CCBatchNode vs ccBlendFunc
引擎版本:2.2.5
放在CCBatchNode下的骨骼動畫設定不了ccBlendFunc,可檢視CCArmature的draw函式,第一句就是判斷batchnode是否為空,
想想也是,要是每個動畫都有自己的ccBlendFunc,那就沒必要放在batchnode下了。