cocos2d-x採用引用計數的方式來管理物件的持有和釋放,所謂引用計數就是每個物件都會有一個屬性用來記錄當前被引用之次數,當要釋放記憶體的時候會根據這個引用計數來確定是否要用delete()方法來釋放這個物件佔用的記憶體。
回到正題看autoRelease()這個方法,以Java觀點來看原以為調用這個方法後物件就被加到了一個自動化記憶體管理器裡,就可如在Java裡面一樣new物件以後就可放任不管,由系統自動判斷在適當時機進行物件回收,但在C++本身實現並不能做到像Java一樣程度的自動記憶體管理,可看autoRelease() 方法的代碼內容如下:
CCPoolManager::sharedPoolManager()->addObject(this);
由代碼之意是把當前物件加到一個記憶體池物件中,再追溯根源查看CCPoolManager類,可進行分析代碼作解讀,但筆者將其採用之運作原理歸納如下:
n   當一個物件被加到CCPoolManager裡面以後這個物件的引用計數被設為1(此時未再透過retain()方法調用它的情況下),若在CCDirect類的主迴圈方法mainLoop()裡面會調用CCPoolManager類的pop()方法,pop()方法的作用其實只有一個:把當前持有的物件引用作釋放,並同時調用物件之autoRelease()方法通知CCPoolManager類(※此時物件有可能被釋放也有可能不釋放,這取決於引用計數之數值),pop()方法被調用以後,之前通過autoRelease()方法加到CCPoolManager類中之同類型物件便不再管理,因已放棄對這類物件的引用,故須知這個autoRelease()方法之作用其實只是通知CCPoolManager類所管理之物件而已,是否完全釋放物件取決於引用計數之數值而定。
上述作法是cocos2d-x記憶體管理機制之規則,當調用retain()方法或透過new生成物件必須與autoRelease()成對出現,不管在何處構造物件當調用了某個物件的retain()方法時,那麼在解構時就一定要調用該物件的autoRelease()方法告知CCPoolManager類進行管理。
一般在寫代碼時通常只是把一個Sprite加到Layer中,實際上是加入到CCNode的一個陣列中,此在加入這個陣列過程中會調用物件的retain()方法,在移除物件時會調用autoRelease()方法。同時在建構函式時Layer也會調用這個陣列的autoRelease()方法,陣列又調用它所持有物件的autoRelease()方法,此實現機制還是內部會自動以引用計數進行管控,但須注意的是,物件是否完全被釋放的問題,在寫代碼時還是要小心作判讀,以免記憶體產生溢出現象。
總結一下:autoRelease()主要是用來管理方法作用域內通過new創建物件之記憶體釋放,以達到如普通定義之物件一樣在方法調用一結束時就進行釋放。具體作法可參考CCObeject類之預設構造函數、retain()autoRelease()方法。

※後序:記憶體管理對嵌入型裝置尤為重要,開發程式時應多注意,避免溢出現象(記憶體不足)產生。


此篇文章有點硬,是講述cocos2d-x如何在不同平台中作適配的底層技術,由於cocos2d-x可跨平臺,如 Android , iOS, BlackBerry 因此它必須針對不同平臺作適配,此適配須包括:
1) 螢幕顯示
2) 用戶輸入
3) 進程主迴圈
4) 資源檔 (圖片,音樂)
Android 的應用程式是 Apk型式,此 Apk 類似一個 Zip .,其如下步驟處理資源檔:
1) Cocos2dxHelper 初始化時會把 Java 層的 ApkPath 傳遞到 native
2) native層的 CCFileUtils在使用 shareFileUtils() 初始化時,會新建自己的衍生類 CCFileUtilsAndroid,並把 apk 解開到臨時目錄,程式運行中要load資源檔的時候, 就到臨時目錄去找。
3) 在程式退出時, 這個臨時目錄會被刪除。
※補充::實際上shareFileUtils() 就在CCFileUtilsAndroid.cpp中實現對Android適配之能力,不會生成 iOS 版本,它是在CCFileUtilsiOS.cpp 中。
Cocos2d-x 提供了幾個Java 層的適配類,它們在 Cocos2dxActivity onCreate()中被初始化,如下圖所示:
1) 上面有提到Cocos2dxHelper,可看它的 init()被調用之情形。
2) 由於Cocos2dxGLSurfaceView衍生於 GLSurfaceView,故可直接調用 opengl的函數繪圖,並在此View 中顯示。
3) 主要的邏輯都在Cocos2dxRenderer中完成,此為最重要的部份。

Cocos2dxRenderer

1) onSurfaceCreated nativeInit()被調用,cocos2d-x所有重要物件( CCDirector, CCSence, HelloWorld ) 都是這裡初始化的。
2) 調用onDrawFrame()時通知cocos2d-x進行繪製一幀。
另外在輸入的處理也是通過Cocos2dxRenderer Androidjava層傳遞到cocos2d-x native 層,下面這張圖描述了 cocos2d-x的物件是如何初始化的。
onSurfaceCreated nativeInit()被調用時即可以使用opengl進行繪圖作業,進行初始化,如下步驟:
1) 根據 Android 提供螢幕大小資訊設置 FrameSize
2) 新建 AppDelegate,此AppDelegateCCApplication的衍生類,當AppDelegaterun()被調用時它會調用到applicationDidFinishLaunching
3) applicationDidFinishLaunching Director, Scene 都被創建。
4) 最後讓Director運行 Scence
通過以上這些cocos2d-x就被適配 Android 系統中。
後序:此篇講述cocos2d-x是如何適配於Android平台之整個流程,概念上非常清楚可供參考用,此種牽涉至底層技術部份對一般之程式開發工作人員可能不會去注意它,但如果懂得它的舖局對遊戲開發之流程作業很有幫助的。etx s2d-x


Windows下開發cocos2d-x遊戲設計,官網在釋出版本中建議採用微軟VS軟體作先期作業,之後要移植至手機適用之Android平台上得再利用cocos2d-x提供之執行命令(※須於命令模式下操作)建立專案後,完成此中間流程還得於Eclipse中將程式導入,筆者之前都是採用此模式作業,有時還須安裝其它軟體來支援,如cygwin架設一個迷小Linux模擬系統,對熟悉程式開發之程序員這不算什麼大工程,但筆者有時一直在想此一定會有改進方案,可能VS在未來版本會提供完整之支援方案,或在Eclipse中可透過外掛插件將必要功能安裝進來即可畢其功於一役,省去開發環境之往返切換,近日到Android官網查看文件(http://tools.android.com/recent/usingthendkplugin)及網搜一些進階程序員之開發技巧,找出一個目前極佳的解決方案,當要進行此篇模式之開發環境改善作業,你得具備之前建置環境之概念(※可參考筆者之前post文章,相同流程部份不再講述)再進行後續工作才能得心應手,有幾個較重要之差異點列舉如下:
u   本篇不採用VS 作為開發環境,C++編碼工作可在Eclipse下進行。(VS太龐大且收費高,通用於微軟性質模式之封閉開發,而Eclipse則為Open Source且擴充彈性大)
u   編譯C++代碼不採用透過由cocos2d-x建置專案時自動給予之build_native.sh腳本指令來進行(※因此指令須配合cygwin模擬系統支援作業),而改採NDK   r5版本以上提供之ndk-build.cmd指令,此指令可直接設定於Eclipse中管理即可在視窗模式中進行作業。
記著此篇重點是”改善開發環境之解決方案”而不是全新從頭做起之開發環境建置,一些必備軟體請先行安裝妥置,如coccos2d-xEclipse+Android SDK+Android NDK,這個開發環境方案才是筆者當初一直想用之模式(※因筆者之前開發Android App應用程式時即全都在Eclipse作業,日後切入學習cocos2d-x遊戲引擎時也一直在找此解決方案)
安裝NDK Plugin
Ø   Eclipse執行功能表Help>>Install New Software
Ø   於彈出視窗中之”Work with:“鍵入https://dl-ssl.google.com/android/eclipse/
Ø   待畫面會出現”Developer Tools”及”NDK Plugins”選項時全部選取>>Next>>同意協議>>安裝完成>>重啟Eclipse
Ø   重啟Eclipse後執行Windows>>Preferences>>左側展開Android>>選取NDK,在此處設定NDK安裝根目錄,如C:\android-ndk-r8e
導入cocos2d-x目錄下的示例遊戲
此處以cocos2d-2.1rc0-x-2.1.3/samples/Cpp/SimpleGame自帶之示例遊戲為例作說明:
1.       導入libcocos2d-x函式庫:以滑鼠右鍵點擊Package Explorer空白區域>>Import>>Existing Android Code Into Workspace>>於視窗之Root Directory設為C:\cocos2d-2.1rc0-x-2.1.3/cocos2dx/platform/android/java目錄下,並選取libcocos2dx導入函式庫
2.       依照前步驟導入cocos2d-2.1rc0-x-2.1.3/samples/Cpp/SimpleGame/proj.android示例
此時在Eclipse裡已存在兩個專案:libcocos2dxSimpleGame
設置使用ndk-build來編譯

預先工作:由於不採用cocos2d-x自帶之build_native.sh來進行編譯,故須先將示例使用之資源檔放置專案之assets目錄下,具體作法是把cocos2d-2.1rc0-x-2.1.3/samples/Cpp/SimpleGame/Resources下之所有檔案複製到cocos2d-2.1rc0-x-2.1.3/samples/Cpp/SimpleGame/proj.android/assets目錄下

1.       Package Explorer裡以滑鼠右鍵點擊SimpleGame專案>>Properties>>於左側欄中展開C/C++ Builder>>選取Tool Chain Editor並作如下操作
2.       於左側欄中選取C/C++ Builder>>於右側欄中之BuilderBuild command框中鍵入ndk-build NDK_DEBUG=1
3.       進行編譯,以滑鼠右鍵點擊SimpleGame專案>>Build All,此時在控制台會輸出錯誤訊息,其意為NDK_MODULE_PATH設定有誤 
4.       此錯誤原因乃NDK_MODULE_PATH無法找到編譯過程中需要之函式庫,其解決方法有二:一是直接修改NDK_MODULE_PATH設置參數使其指定至使用之函式庫目錄位置;二是將會使用到之函式庫自cocos2d-2.1rc0-x-2.1.3目錄拷貝一份置放於專案目錄下,但因第一種方法設置NDK_MODULE_PATH參數會造成無法調試C++代碼(※不知何故?不過此法應是最佳方案,筆者之前有看過類似文章,証明可行後再補述),故採用第二種方法來解決:把編譯過程中需要的函式庫拷貝到系統預設的NDK_MODULE_PATH(※過渡期作法,但非為最佳方案)
5.       複製cocos2d-2.1rc0-x-2.1.3目錄下的cocos2dx,CocosDenshion,extensions,external4個目錄到NDK安裝目錄下之sources目錄中,如C:\android-ndk-r8e\sources
6.       再複製cocos2d-2.1rc0-x-2.1.3\cocos2dx/platform\third_party\android\prebuilt目錄的所有檔案到NDK安裝目錄下之sources目錄中。(※有libcurl,libjpeg,libpng,libtiff,libwebp檔案)
7.       重新編譯,以滑鼠右鍵點擊SimpleGame專案>>Build All,此時會編譯成功。(※不成功便成仁,重新Check之前動作)
修改專案檔案結構(使CDT可識別C++)
為讓Eclipse中之C++代碼可設定中斷點,則須修改當前專案之檔案結構使之可運行:
1.       將示例下之cocos2d-2.1rc0-x-2.1.3\samples\Cpp\SimpleGame\Classes目錄移動至cocos2d-2.1rc0-x-2.1.3\samples\Cpp\SimpleGame\proj.android/jni下之位置
2.       修改cocos2d-2.1rc0-x-2.1.3/samples/Cpp/SimpleGame/proj.android/jni下之Android.mk使檔案可指向正確的位置,如下:
LOCAL_SRC_FILES := hellocpp/main.cpp \
               Classes/AppDelegate.cpp \
               Classes/HelloWorldScene.cpp \
                Classes/GameOverScene.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)/Classes    
3.       重新編譯,以滑鼠右鍵點擊SimpleGame專案>>Build All,此時會編譯成功。
調試
1.           Classes目錄下的HelloWorldScene.cpp檔裡之ccTouchesEnd方法下一個中斷點,這樣遊戲運行後,點擊螢幕應該可以觸發我們的中斷點
2.           將手機連接到電腦上,以滑鼠右鍵點擊SimpleGame專案>> Debug As>>Android Native Application>>選擇手機型式機號>>調試
3.           遊戲運行起來後,觸控手機螢幕試試。此時Eclipse自動切換到了Debug模式,且成功的中斷點下來,至於變數可在右邊視窗查看,可執行Debug介面上之按鈕試試運作狀況如繼續執行、單步執行。
後序:上述操作中複製了cocos2dx下許多檔案到NDK目錄下,顯得有點繁瑣,此種作法是為了避開去設置NDK_MODULE_PATH參數,因一旦設置了NDK_MODULE_PATH參數會使得調試變得不可行,此非不得已之作法,但透過參數設定應是更好的方法,待解決!