引言:咱們使用cocos2d-x引擎製做了一款飛行射擊遊戲,其中創新性地融入了手勢識別功能。可是咱們在移植過程當中遇到了不少的問題,同時也發現網上的資料少而不全。因此在項目行將結束的時候,咱們特意寫了這篇文章來完整記錄咱們整個移植的過程,記念咱們項目的成功完成,更以此來表達對幫助過咱們的人的感謝。移植過程當中咱們在網上獲得了不少幫助,更要感謝黃楊學長在最後時刻幫助咱們突破難關!html
0、開發平臺java
系統:win8 profession 64bitlinux
IDE:vs2012 rtm, eclipseandroid
cocos2d-x版本:2.1.2c++
一、移植準備windows
在windows下移植咱們須要以下環境支持:Android SDK、 NDK、 Eclipse、 Cygwin.安全
1.1下載Cygwin安裝程序bash
在Cygwin官網上找(http://cygwin.com/install.html)到在線安裝程序,下載對應版本。這裏我選擇 windows 64bit版本。app
1.2 Cygwin安裝過程eclipse
打開下載好的setup-x86_64.exe,可一路單擊下一步(篇幅所限,太過細節的問題就不一一闡述了),直到以下頁面:
選擇下載的站點,正確選擇站點以後下載會很快。咱們(在北航)選擇了ftp://mirrors.neusoft.edu.cn,速度仍是挺快的。這裏要提醒你們注意,並非全部站點的下載都是完整的!Rylynn(博客名)選擇的好幾個站點都下載不完整,你們若是遇到這個問題,可嘗試不一樣的站點。
選擇完站點以後將出現如上界面,這是要選擇安裝包。爲了使Cywin可以編譯程序,咱們須要選擇一些必要的組件。在不改動默認選擇的前提下,咱們須要保證在Devel分支裏以下包已經被選中:binutils, gcc-c++,gcc-core,gdb,make,mingw-gcc-core,mingw-gcc-c++。安裝成功後,運行Cygwin,能夠在Cygwin窗口中分別輸入gcc+ -v, g++ -version, make -v, gdb -v等命令並回車,若是看到窗口輸出了各組件的版本信息,那麼說明安裝成功。若是輸入某條命令,窗口輸出 command not found,那麼就須要從新打開安裝程序並安裝對應的組件,不須要所有從新安裝。
1.3 安裝Eclipse、Android SDK、 Android NDK
這裏提供網站連接,你們可自行下載和安裝。NDK下載後解壓便可。Eclipse的安裝和環境配置,請你們參考相應的文章,在此再也不贅述。
Android SDK:http://developer.android.com/sdk/index.html
Android NDK:http://developer.android.com/tools/sdk/ndk/index.html
Eclipse:http://www.eclipse.org/downloads/
1.4 編輯create-android-project腳本
在cocos2d-x引擎的根目錄下,能夠找到create-android-project腳本。在windows下,對應的是"create-android-project.bat",這個腳本用於生成遊戲的android工程。
使用任何支持unix風格換行的編輯器(咱們選擇了Ultra Editor)打開腳本文件,找到以下語句,並進行修改。
set _CYGBIN = e:\cygwin\bin
set _ANDROIDTOOLS =e:\android\andoird-sdk\tools
set _NDKROOT = e:\android\android-ndk-r8d
其中將_CYGBIN設置爲Cygwin安裝目錄下的"bin"文件夾路徑,_ANDROIDTOOLS設置爲Andoird SDK安裝路徑下"tools"文件夾路徑,_NDKROOT設置爲NDK的解壓路徑。
完成設置後,在Cygwin中運行"create-android-project"腳本(可直接將文件拖入Cygwin窗口後回車)。若提示以下,則修改爲功:
Input package path. For example: org.cocos2dx.example:
二、生成項目
接下來咱們執行create-android-project腳本。用Cygwin運行"create-android-project.bat",看到以下提示:
Input package path. For example: org.cocos2dx.example:
此時輸入咱們想要建立的程序包名(程序包的命名應遵照Andoird命名規範)。咱們輸入:"org.cocofish.skyline"(咱們這個項目的隊名叫cocofish,項目叫作skyline。你們可隨意選擇,只要記住就好)。回車後,窗口輸出:
Input project name:
咱們輸入了"Skyline"
回車後,窗口會列出計算機中安裝的全部Android SDK版本,你們能夠根據須要自行選擇。咱們輸入了"1",即選擇android 4.1.2的版本。在Lmeng(博客名)的計算機裏,整個過程窗口輸出的內容貼在下方:
Please enter your package path. For example: org.cocos2dx.example:org.cocofish.skyline Please enter your project name:Skyline "Now cocos2d-x suppurts Android 2.1-update1, 2.2, 2.3 & 3.0" "Other versions have not tested." Available Android targets: ---------- id: 1 or "android-16" Name: Android 4.1.2 Type: Platform API level: 16 Revision: 4 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in ABIs : armeabi-v7a, mips, x86 ---------- id: 2 or "Google Inc.:Google APIs:16" Name: Google APIs Type: Add-On Vendor: Google Inc. Revision: 3 Description: Android + Google APIs Based on Android 4.1.2 (API level 16) Libraries: * com.google.android.media.effects (effects.jar) Collection of video effects * com.android.future.usb.accessory (usb.jar) API for USB Accessories * com.google.android.maps (maps.jar) API for Google Maps Skins: WVGA854, WQVGA400, WSVGA, WXGA800-7in, WXGA720, HVGA, WQVGA432, WVGA 800 (default), QVGA, WXGA800 ABIs : armeabi-v7a ---------- id: 3 or "android-17" Name: Android 4.2.2 Type: Platform API level: 17 Revision: 2 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W XGA720, WXGA800, WXGA800-7in ABIs : armeabi-v7a, mips, x86 ---------- id: 4 or "Google Inc.:Google APIs:17" Name: Google APIs Type: Add-On Vendor: Google Inc. Revision: 3 Description: Android + Google APIs Based on Android 4.2.2 (API level 17) Libraries: * com.google.android.media.effects (effects.jar) Collection of video effects * com.android.future.usb.accessory (usb.jar) API for USB Accessories * com.google.android.maps (maps.jar) API for Google Maps Skins: WVGA854, WQVGA400, WSVGA, WXGA800-7in, WXGA720, HVGA, WQVGA432, WVGA 800 (default), QVGA, WXGA800 ABIs : armeabi-v7a Please input target id:1
完成以後,腳本會在根目錄下建立"Skyline"的目錄,並在此目錄裏生成Android項目文件。新建立的項目文件中有Helloworld的項目,你們接着可直接跳到從"執行build_native.sh"繼續後續操做,經過完成這樣一個默認的項目的移植來檢測整個配置和操做過程的正確性。這裏將繼續本身項目的移植。
打開新建立的項目目錄(咱們這裏是"Skyline"),能夠看到"Classes"和"Resources"目錄,腳本會在這兩個目錄下建立默認的Helloworld代碼和資源文件,咱們把它們所有刪除。接着,把咱們本身的項目源碼和資源複製到這兩個目錄裏。一般,咱們將源代碼(.cpp和.h)複製到"Classes"目錄下,把資源文件(圖片,音樂等)複製到"Resources"目錄下。操做完成後,進入下一步。
重要!在新建的項目後,proj.android\jni\hellocpp下,有個main.cpp,是整個項目的入口。直接點擊,會彈出"拒絕訪問"。若是想要查看裏面的內容的話,要先修改它的屬性-安全-高級,在權限條目裏將權限設置爲"徹底控制"(雙擊後可修改)。main.cpp的內容,通常狀況下不須要作修改。
三、編譯
完成上述操做後,咱們要對項目進行編譯,並生成.so文件(unix的動態連接庫,與windows的.dll相似)。
3.1 修改"Android.mk"
"Android.mk"文件位於項目的"proj.android\jni"目錄下,它記錄了項目所包含的源碼文件信息。利用編輯器(如Ultra Editor)打開此文件,參照下面的文件進行修改。/*...*/裏的內容是筆者加上的註釋
LOCAL_PATH := $(call my-dir) /*不改動*/ include $(CLEAR_VARS) /*不改動*/ LOCAL_MODULE := sky_shared /*默認爲game_sharred,若是改動,請必定記住*/ LOCAL_MODULE_FILENAME := libsky /*默認爲libgame,若是改動,請必定記住。*/ LOCAL_SRC_FILES := hellocpp/main.cpp \ ../../Classes/AppDelegate.cpp \ ../../Classes/其餘源文件.cpp /*添加上本身項目裏全部的源文件,結尾的'\'是鏈接符,若是下一行還有內容,請不要漏掉.並且'\'後應直接回車*/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \ $(LOCAL_PATH)/../../../cocos2dx/platform/third_party/win32 \ $(LOCAL_PATH)/../../../extensions /*添加上本身項目裏頭文件所在的目錄。後兩行是筆者由於項目而單獨添加的,前一個是爲線程,後一個是爲 控件類引入的頭文件所在的目錄*/ LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static /*如下均不做改動*/ include $(BUILD_SHARED_LIBRARY) $(call import-module,CocosDenshion/android) \ $(call import-module,cocos2dx) \ $(call import-module,extensions)
重要!出錯點!筆者在這一步遇到不少問題,因此也請讀者加以重視。
(1)對LOCAL_MODULE與LOCAL_MODULE_FILENAME修改後請務必記住本身所修改的名字。好比筆者將它們改成skyline_shared和libskyline。由於這裏的skyline將會在導入eclipse那一步以後用到。咱們須要將在經過執行「create-android-project」建立的項目文件夾裏的"<你的項目名>.java」(好比"skyline.java")這個文件裏System.loadLibrary("game")的「game」改爲本身所修改的名字,在筆者這裏就是"skyline",不然就是黑屏。估計是沒法加載生成的libskyline.so(後面會提到)。筆者由於這個問題糾結了好久!最後才發現原來就一個字符串的事情!!若是不改動前面的LOCAL_MODULE和LOCAL_MODULE_FILENAME,由於默認的是"game",那就不會有問題。
(2)若是你在項目裏引入了線程和控件類,可參考筆者這個代碼框裏的LOCAL_C_INCLUDES。對於線程,請注意:將你引入線程的那個文件裏"#include 'pthread/pthread.h'"改成"#include'pthread.h'",以使編譯可以經過。(筆者不知道緣由,也許沒有這麼麻煩,可是在筆者計算機裏成功了。也但願明白的人告知~)
3.2 執行"build_native.sh"
接下來就啓動編譯了。進入android項目路徑下,使用Cygwin執行"build_native.sh"腳本(tip:可直接將文件拖入Cygwin窗口),若是順利,咱們能夠在Cygwin窗口輸出的最後發現「Install : libsky.so => libs/armeabi/libsky.so」,而且在libs/armeabi目錄下找到編譯得到的"libskyline.so"(注意到了嗎,這是上一步設置的LOCAL_MODULE_FILENAME)。
重要!出錯點!若是此時提示「please define NDK_ROOT」,找到cygwin\home\xxx(你的用戶名)目錄下.bash_profile文件,用文本編輯器打開,在最後加入下面兩行:
NDK_ROOT=/cygdrive/d/Coco/android-ndk-r9
export NDK_ROOT
錯誤將再也不出現。d/Coco/android-ndk-r9 是你ndk解壓目錄,筆者的原目錄是D:\Coco\android-ndk-r9,作相似改動便可。
然而,事情每每不那麼順利!
重要!出錯點!很大可能你會看到Cygwin輸出一大堆亂七八糟的東西,並且在中途停下。這時候就是編譯出錯了。可是千萬不要着急,一點點調。雖然出錯了,可是報錯點仍是很準確的。因此請你們從最上面往下一行一行找。發現有"error"的這行,這就是報錯點。仔細看這行的內容,它很明確地告訴你是哪一個文件哪一行出了錯。這時候去找到那個出錯的位置,根據報錯的信息,查找一些資料,加上本身的判斷和嘗試,把錯誤處理掉。而後再編譯一遍。若是有錯誤,繼續處理。不要看一堆字母感受煩躁(看着就像亂碼的感受),這時候你最須要的就是慢慢來。並且這個錯誤可能來自於引擎代碼自己!!
好比筆者遇到這樣幾個錯誤:
(1)使用了未聲明的"itoa"。因而我去查Classes目錄下的props_number_shower.cpp第27行,確實調用了itoa這個方法。雖然這個在vs2012裏運行沒問題,可是這裏並不支持。因而我從網上找了一個替代itoa功能的函數源代碼,加入到這個源文件中,編譯就經過了。網友涵曦(博客名)提示,這是包含文件的問題。在此表示感謝!
(2)格式問題。一樣的思路,找到CocosDenshion/android/SimpleAudioEngine.cpp第77行。發現了LOGD(deviceModel)(如圖)。上網查了下發現好像linux對格式要求比較嚴格,因而筆者嘗試把這行改成LOGD("%s", deviceModel);發現編譯經過。在編譯的過程當中發現很是多相似的報錯,你們若是看到報錯信息以下圖,找到指定位置修改便可。
(3)文件流。筆者對c++文件流是否能在Cygwin中編譯經過沒有作足夠的測試。可是筆者將fstream換成c的FILE操做的時候就不報錯了,若是你們在這裏遇到問題,能夠嘗試着改改。可是對於移植到android上,還應採CCFileUtils。範例以下:
string fullPath=CCFileUtils::sharedFileUtils()->getWritablePath()+"rank.txt"; /*"rank.txt"是本身使用的資源文件,其餘的不用改動。此行用於得到文件位置*/ unsigned long file_size; /*聲明變量,在下一行中使用,用於接收文件內容大小*/ char *filedata=(char*)CCFileUtils::sharedFileUtils()->getFileData(fullPath.c_str(),"r",&file_size); /*取得文件指針*/ if(filedata==NULL)... /*對於文件指針的用法,與C++同樣*/
若是遇到其餘的錯誤,讀者可按照以上解決問題的思路自行解決問題。
四、導入Eclipse
4.1新建項目
打開Eclipse,一次打開"File"-"New"-"Project"-"Android"-"Android Project from Existing Code"項目,在隨後出現的界面中點擊browser,後找到遊戲項目的"proj.android"並確認,此時即從原有代碼中新建了安卓項目。
4.2複製必要文件
4.2.1將cocos2d-2.1rc0-x-2.1.2(根目錄)\cocos2dx\platform\android\java\src下的文件複製到Sky(遊戲項目根目錄)\proj.android\src裏,並在eclipse中手動導入
4.2.2若是Sky(遊戲項目根目錄)\proj.android\assets裏沒有資源文件,將Sky(遊戲項目根目錄)\Resources下你的全部資源文件複製到assets中,並在eclipse中手動導入
4.3 作必要的修改
4.3.1 在Sky(遊戲根目錄)\src\<項目名>裏的Sky.java文件裏,下圖所標示的那行中,請記得將loadLibrary("xxx");裏的字符串改成先前修改過的LOCAL_MODULE_FILENAME的值(去掉lib),如筆者改成sky。注意!這在上面已經強調過,若是這裏的字符串和LOCAL_MODULE_FILENAME(去掉lib)的不匹配,結果很慘烈!看不見界面!筆者在這裏費了不少時間!
4.3.2 其餘簡單的錯誤,好比下圖所示:找不到drawable/icon,可在eclipse工程中res里加入一個icon.png文件便可。固然也可將icon更名成其餘以存在於工程的圖片文件(通常爲png文件)
五、調試
虛擬機十分卡,並且好像並不支持opengl,因此建議使用真機進行調試(使用方法這裏就不詳細展開,你們可在網上查閱相關資料)。調試過程當中不免發生問題,這裏將列舉出筆者在調試過程當中遇到的問題,探討解決的思路。
5.1 文件權限問題。在調試過程當中咱們在logcat message窗口看到這樣一個錯誤,意思是某個文件權限不夠。若是這時候你們複製這麼長串的看起來像目錄的東西去搜索,是找不到的。由於他們畢竟不是目錄名。這個時候,你們能夠選去關鍵詞去搜索。好比這張圖片裏,咱們認爲"shader"是關鍵詞,果真在項目安卓工程裏找到了"shaders"文件夾,將裏面全部文件的權限修改爲「徹底控制」,發現調試再也不報錯,能夠認爲修改爲功!
5.2文件讀寫問題
某種意義上筆者並不肯意把它稱做文件讀寫問題。後面將作解釋。
若是讀者還記得的話,上面已經提到過讀寫問題。若是單純採用C的文件讀寫寫法,工程就會找不到資源文件。所以將它改爲上述的CCFileUtils,將解決此類問題。
string fullPath=CCFileUtils::sharedFileUtils()->getWritablePath()+"rank.txt"; /*"rank.txt"是本身使用的資源文件,其餘的不用改動。此行用於得到文件位置*/ unsigned long file_size; /*聲明變量,在下一行中使用,用於接收文件內容大小*/ char *filedata=(char*)CCFileUtils::sharedFileUtils()->getFileData(fullPath.c_str(),"r",&file_size); /*取得文件指針*/ if(filedata==NULL)...
5.3 如何調試
之因此說讀者不肯意把「5.2文件讀寫問題」稱做「文件讀寫問題」,是由於讀者在解決這類問題的時候使用的方法實際上是告訴了咱們如何進行調試。筆者在完成5.1那一步以後發現真機上仍是沒有顯示出任何內容。黑屏!這個時候咱們着急了,曾經已經將helloword顯示在手機上了,爲何這個項目就不能夠?!學長提示咱們是否是主菜單加載不成功,並知道咱們對每個關鍵部分加上一個輸出,經過在控制檯的輸出查看哪一步出了問題!好比咱們在主菜單"mainmenu.cpp"的"init()"裏每個加載操做後加上了CCLOG("%s","init() xxx;--From MainMenu")("xxx"這裏改爲特定的值,用於肯定出錯位置)。也是經過這個方法,咱們才肯定了全部的「文件讀寫問題」。所以,若是你們遇到問題,請你們不要氣餒,一點點地去判斷出錯位置,而後修改,嘗試。
六、分辨率適配
最後一個問題就是分辨率適配了。在網上翻看了相關資料後,總算解決了問題。其實就是一行代碼的事情。
在 AppDelegate.cpp的 bool AppDelegate::applicationDidFinishLaunching() 方法裏,加上
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(576,324,kResolutionNoBorder);便可解決分辨率適配問題。
其中,576,324 是筆者在win32設計遊戲時採用的寬度和高度,你們改成本身所設置的寬高便可。kResolutionNoBorder是指在屏幕拉伸時採用的其中一種策略,保證拉伸後無邊界,可是設計時界面的邊緣部分可能在最後被遮蓋。筆者經過vs2012的 "go to definition"操做找到了以下的定義。如下便是所有的適配策略了。
enum ResolutionPolicy { // The entire application is visible in the specified area without trying to preserve the original aspect ratio. // Distortion can occur, and the application may appear stretched or compressed. kResolutionExactFit, // The entire application fills the specified area, without distortion but possibly with some cropping, // while maintaining the original aspect ratio of the application. kResolutionNoBorder, // The entire application is visible in the specified area without distortion while maintaining the original // aspect ratio of the application. Borders can appear on two sides of the application. kResolutionShowAll, kResolutionUnKnown, };
參考資料:參考的資料較爲零碎,多爲網上的文章。由於比較繁亂,沒有記錄下來。另外參考了《Cocos2d-x高級開發教程》的移植部分。
總結:
筆者和隊友在整個移植過程當中備受煎熬,幾近絕望。可是始終相信既然別人可以移植成功,咱們也必定能夠!最終咱們用了兩天多的時間終於讓咱們的遊戲成功運行在手機上!那個興奮感、那種絕處逢生的快感到如今還十分難忘!因此請各位cocos2d-x的戰友們不要氣餒,問題都是能夠解決的,一點一點來,不要着急,給本身信心。先把helloworld顯示出來,而後再把本身的項目慢慢調出來。堅持下去,總會成功的!
Here is our game <SkyLine Beta1.0>, Please download it to support us!!!
但願這篇文章可以幫到困擾在cocosd-x移植android過程當中的朋友們。若是文章內容與錯誤或者某些部分有更好的解法,也請留言。咱們很但願和你們交流經驗!謝謝!