Cocos2d-x跨平台开发文档总结

Cocos2d-x跨平台开发文档

 

0.一些说明

本文档基于以win32作为开发编码平台然后移植到其它平台的cocos2d-x开发方法,下面介绍个人从网上收集来的不错的cocos2d-x开发方法以及一些改进意见。

         可能还存在一些小问题,大家多交流~

 

1.    从win32移植到android

参考教程:老G:http://4137613.blog.51cto.com/4127613/758783

 

1.0 准备工作:配置android工程生成器

需要说明的一点是:cygwin安装时最好不要改其安装目录。

#1用ue之类的编辑器打开cocos2d-x目录下的create-android-project.bat

 

#2编辑这三个变量

 


 

1.1创建android工程

 

#1运行cocos2d-x目录下的create-android-project.bat

注意:如果是在win7开发,右击->以管理员权限运行,可能会产生生成的目录有读写权限问题,暂时无解。

 

#2然后首先输入包名和项目名。

注意有坑!这会删除和覆盖你在cocos2d-x安装目录下同名文件夹,如果你建立了一个同名项目(有的话一般是win32的)的话。



#3然后输入支持系统版本,android是向下兼容的。我这里写5,也就是android2.1-update1


然后项目就建立好了,你会发现在cocos2d-x安装目录(根目录)下,多了个Test文件夹

 

1.2导入代码和资源

 

#1打开Test

 

#2我们看到有三个文件夹,其中android就是android项目文件夹

 

把你win32项目里的Classes中的.h和.cpp文件全部拷贝到当前Classes下(注意删除Classes里面的多余的cpp和h,就是项目自动生成的那些)

把你win32项目里的Resources中的资源文件全部拷贝到当前Resources下(注意替换或删除自动生成的资源文件)

 

 

 

 

1.3编辑mk文件

修改MK文件的目的是让NDK在创建so的时候知道去哪找cpp

#1注意有坑!android项目里有一大堆mk,而且不同的教程说的mk位置还不一样!你编辑错误了,是无效的(跟你实际使用的mk也有关系)。在这个例子中,我们使用的是Classes下的mk

 

#2要修改的地方如下

LOCAL_SRC_FILES:在这里加入你Classes下的cpp文件,不需要加.h文件!

LOCAL_C_INCLUDES:在这里添加你使用的库的h文件,如果有的话

LOCAL_LDLIBS:在这里添加你使用的库的lib文件,如果有的话

 

这里使用的是 “是男人就坚持20秒”那个例子的代码

 

注意,第三方库和额外的库都是要自己添加的。默认生成的mk里没那么全。比如引擎自带的box2d、curl、chipmunk等也同样需要自己添加包含文件夹以及lib文件!

 

 

 

 

 

 

 

 

 

#3下面详细介绍如何修改mk文件,以添加box2d为例。

以在HelloWorld中添加Box2D为例,记录一下需要注意的坑。BallCC是HelloWorld对应的Android工程,红色字体是需要改动的地方。

 

第一步:

Additional Include Directories中加入

$(SolutionDir)

 

第二步:

Additional Dependencies中加入

libbox2d.lib

 

前两步是保证在VS中能够运行,与Android无关。

 

第三步:

F:\Dev\cocos2d-1.0.1-x-0.10.0-Clent\BallCC\Classes

下的Android.mk修改为

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := game_logic

 

LOCAL_SRC_FILES := AppDelegate.cpp \

                   HelloWorldScene.cpp \

                   sdBall.cpp \

                   sdDangBan.cpp \

                   ODSocket.cpp

                  

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../cocos2dx \

                    $(LOCAL_PATH)/../../cocos2dx/platform \

                    $(LOCAL_PATH)/../../cocos2dx/include \

                    $(LOCAL_PATH)/../../CocosDenshion/include \

                    $(LOCAL_PATH)/../../cocos2dx/lua_support \

                    $(LOCAL_PATH)/../..

                   

LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../android/libs/$(TARGET_ARCH_ABI)) \

                -lcocos2d -lcocosdenshion -lbox2d \

                -L$(call host-path, $(LOCAL_PATH)/../../cocos2dx/platform/third_party/android/libraries/$(TARGET_ARCH_ABI)) -lcurl

           

include $(BUILD_SHARED_LIBRARY)

 

第四步:

F:\Dev\cocos2d-1.0.1-x-0.10.0-Clent\BallCC\android\jni

下的Android.mk修改为

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

 

subdirs := $(addprefix $(LOCAL_PATH)/../../../,$(addsuffix /Android.mk, \

           Box2D \

           cocos2dx \

           CocosDenshion/android \

         ))

subdirs += $(LOCAL_PATH)/../../Classes/Android.mk $(LOCAL_PATH)/helloworld/Android.mk

 

include $(subdirs)

 

第五步:

F:\Dev\cocos2d-1.0.1-x-0.10.0-Clent\BallCC\android\jni

下的Application.mk修改为

# it is needed for ndk-r5

APP_STL := stlport_static

APP_MODULES := cocos2d cocosdenshion box2d game_logic game

 

第六步

F:\Dev\cocos2d-1.0.1-x-0.10.0-Clent\BallCC\android\src\com\android\BallCC

下的BallCC.java中增加

     static {

              System.loadLibrary("cocos2d");

              System.loadLibrary("cocosdenshion");

              System.loadLibrary("box2d");

              System.loadLibrary("game_logic");

         System.loadLibrary("game");

     }

太多坑。。。

最后一步不搞的话,编译都没问题,但是在手机上跑就会崩溃。

这里为什么在手机上会崩溃,原因如下:

我们这里的开发是“C++ + java”的模式,java是运行在dvk中,而C++Native代码,这两者通过JNI交互,至于怎么交互的如下

Cocos2dxActivity中可以看到这样的一段代码private static native void nativeSetPaths(String apkPath);多了个native字段,它是告诉JNI这个方法要到动态链接库中去找到这个方法,并执行它(so中有与之对应的方法)。到哪里去找这个so呢:

static {

     System.loadLibrary("cocos2d");

     System.loadLibrary("cocosdenshion");

     System.loadLibrary("game_logic");

         System.loadLibrary("game");

     }

到这里来找,cocos2d中没有,就到下一个,直到找到为止。若果找不到就会报错。

 

 

#4额外说明

 

你可能会遇到打包好apk并安装运行的cocos2d-x程序在android手机上触碰屏幕就崩溃的泪奔情况,crash in cocos on touch !

 

解决方法:打开: android工程/jni/Application.mk ,将首行:APP_STL:= stlport_static,修改为:APP_STL := gnustl_static 。

这里需要说明的是APP_STL的值是来指定静态库,前者使用STLport作为静态库,后者使用 GNUlibstdc++ 作为静态库,默认情况下STLPORT是不支持C++异常处理和RTTI,所以不要出现 -fexceptions -frtti(问题在这里,望在探索!),如果真的需要可以使用gnustl_static来支持标准C++的特性,但生成的文件体积会偏大,运行效率会低一些。

 

注意:gnustl不支持hash_map,只能改用map。

 

1.4运行android工程目录下的build_native.sh生成 .so库

 

#1运行你的cygwin安装目录下的Cygwin.bat或者Cygwin Terminal启动Cygwin。

 

#2进入当前Test\android路径。

 

注意cygwin下的命令写法,和win下不同


#3运行build_native.sh脚本


头一次编译会长些,当然图省事你也可以把自己及其他的android项目里面的so复制进来(应该可以把,哈哈哈)

编译完然后你会看到,在android文件夹下面生成了一大堆东西。

 

 

1.5导入eclipse

 

#1注意有坑!使用新建android项目下的Create project from existingsource,如果你使用的是“导入”有可能无法识别。


#2导入成功,然后就是编译执行了。cocos2d-x作者walzer推荐用.sh编译so,再用eclipse编译成apk。网上另有一种完全在eclipse里自动编译so的方案,需要使用NDK r7b以上版本,参考地址:http://blog.csdn.net/maojudong/article/details/7261986


 

 

 

1.6其他注意事项:

#1.win32项目对资源文件大小写不敏感,android敏感

#2.可以直接把win32项目里的工程文件,以及win32文件夹复制进来,项目就可以和VS共用了,当然cocos2d-x也是这么干的

#3.vs用的是gb码,android用的是utf-8,解决方法在vs下用iconv,另外最好全都转成utf-8,网上有很多编码批量转换工具

#4.android的横竖屏问题错乱,在android下把

pDirector->setDeviceOrientation(kCCDeviceOrientationLandscapeLeft);

这句用条件编译宏给关掉

 

 

 

 

 

 

 

 

2.    Android屏幕自适应方案

主要参考教程:http://www.himigame.com/android-game/799.html

 

2.1首先对生成的android项目下main.cpp文件进行修改

 

直接在编译好的android项目中按如下路径查找:

 

your android name/Jni/helloworld/main.cpp

 

打开main.cpp,看到如下代码段:

 

// if you want to run in WVGA with HVGAresource, set it

//view->create(480, 320);

 

这里view->create(480,320);默认是关闭的,这里打开即可;打开任意的一个cocos2d-x项目,找到AppDelegate.cpp文件就能看到

 

这里我们进行一些预处理,假定对于所有分辨率的屏幕我们都给它设定逻辑点阵横向时的高为320,这点很重要!注意:在高分屏上逻辑点对应2*2的像素点,所以逻辑点阵的高仍然为320。添加如下代码:

 

float scaleH = (float)h/320;

int viewWidth = (int)(w/scaleH);

view->create(viewWidth, 320);

 

 

2.2让android版项目使用iOSRetina类似@2x的-hd功能,直接使用-hd高清图片

 

#1找到cocos2d-x引擎根目录下cocos2dx/platform/android/CCEGLView_android.cpp , 打开,找到 void CCEGLView::create(int width, int height)函数,函数内置换如下代码:

 

voidCCEGLView::create(intwidth, intheight)

{

 

    if(width == 0 || height == 0)

    {

        return;

    }

 

    m_sSizeInPoint.width= width;

    m_sSizeInPoint.height= height;

 

    //calculate the factor and the rect of viewport

    m_fScreenScaleFactor=  MIN((float)m_sSizeInPixel.width / m_sSizeInPoint.width,(float)m_sSizeInPixel.height / m_sSizeInPoint.height);

    CCLOG("CCEGLView::Create/ Screen Scale Factor = %f", m_fScreenScaleFactor);

    if(m_fScreenScaleFactor >= 1.5f)

    {

        CCLOG("CCEGLView::Create/ HD Scale Factor => Increase Content Scale Factor");

        cocos2d::CCDirector::sharedDirector()->setContentScaleFactor(2.0f);

    }

    intviewPortW = (int)(m_sSizeInPoint.width *m_fScreenScaleFactor);

    intviewPortH = (int)(m_sSizeInPoint.height *m_fScreenScaleFactor);

    m_rcViewPort.origin.x= (m_sSizeInPixel.width - viewPortW) / 2;

    m_rcViewPort.origin.y= (m_sSizeInPixel.height - viewPortH) / 2;

    m_rcViewPort.size.width= viewPortW;

    m_rcViewPort.size.height= viewPortH;

 

    m_bNotHVGA= true;

}

 

 

#2继续在你的项目下找到CCFileUtils_android.cpp类(位置:cocos2dx/platform/android/

CCFileUtils_android.cpp),双击打开。

 

找到 const char* CCFileUtils::fullPathFromRelativePath(const char*pszRelativePath) 函数,然后替换如下内容:

 

constchar* CCFileUtils::fullPathFromRelativePath(constchar*pszRelativePath)

{

 

    if(CC_CONTENT_SCALE_FACTOR() == 2.0f)

    {

 

        //CC_RETINA_DISPLAY_FILENAME_SUFFIX

        //verifier si suffix deja present

        std::stringpath = pszRelativePath;

        std::string::size_typepos = path.rfind("/") + 1; // the begin index of last part of path

 

        std::string::size_typesuffixPos = path.rfind(CC_RETINA_DISPLAY_FILENAME_SUFFIX);

        if((std::string::npos != suffixPos)&& (suffixPos > pos))

        {

            //=> if yes, return path directly

        }

        else

        {

            //=> if no, add "retina"/hd suffix and test if file exist

            CCString*pRet = newCCString();

            pRet->autorelease();

            pRet->m_sString= path.substr(0, path.rfind(".")) + CC_RETINA_DISPLAY_FILENAME_SUFFIX+ path.substr(path.rfind("."), path.length());

 

            if(existFileData(pRet->m_sString.c_str()))

            {

                //   => if yes, return path with suffix

                CCLog("cocos2d:FilePath(%s) with suffix(%s) exist, use it.", pRet->m_sString.c_str(),CC_RETINA_DISPLAY_FILENAME_SUFFIX);

 

                returnpRet->m_sString.c_str();

            }

            else

            {

                //   => if no, return path without suffix

            }

        }

    }  

 

    returnpszRelativePath;

}

 

 

#3接下来在本类中添加如下两个函数:

 

boolCCFileUtils::existFileData(constchar* pszFileName)

{

    stringfullPath(pszFileName);

 

    if((! pszFileName))

    {

        returnfalse;

    }

 

    if(pszFileName[0] != '/')

    {

        //read from apk

        fullPath.insert(0,"assets/");

        returnCCFileUtils::existFileDataFromZip(s_strResourcePath.c_str(),fullPath.c_str());

    }

    else

    {

        do

        {

            //read rrom other path than user set it

            FILE*fp = fopen(pszFileName, "rb");

            if(fp != NULL)

            {

                fclose(fp);

                returntrue;

            }

        }

        while(0);

    }

    returnfalse;

}

boolCCFileUtils::existFileDataFromZip(constchar* pszZipFilePath, constchar* pszFileName)

{

    unzFile pFile =NULL;

    boolres = false;

    do

    {

        CC_BREAK_IF(!pszZipFilePath|| !pszFileName);

        CC_BREAK_IF(strlen(pszZipFilePath)== 0);

 

        pFile= unzOpen(pszZipFilePath);

 

        intnRet = unzLocateFile(pFile, pszFileName,1);

        res= UNZ_OK == nRet;

 

    } while(0);

 

    if(pFile)

    {

        unzClose(pFile);

    }

    returnres;

}

 

 

#4当然,别忘了在CCFileUtils.h(位置:cocos2dx/platform/CCFileUtils.h)中声明两个函数的定义:

 

staticboolexistFileData(constchar* pszFileName);

staticboolexistFileDataFromZip(constchar* pszZipFilePath, constchar* pszFileName);

 

 

#5编译你的项目到android运行看看实际效果。注意:本方法会对android手机的屏幕进行逻辑点坐标转换,纵向的y区间为[0, 320] ,而x的区间则是根据实际屏幕的宽高比等比例计算得出。例如:WVGA/480*800的屏,它的逻辑点坐标是320*533 ;qHD/540*960的屏,它的逻辑点坐标是320*569

 

所以,在不同分辨率的android手机上我们可以使用同一的逻辑点高度320,这个包括在iphone也是一致的,这就保证了代码的通用性。当然,宽度是不固定的,所以在编程时注意在横向定位时尽量采用相对位置,而不是把横坐标写死

 

Cocos2d-x使用逻辑点,逻辑点按照缩放比例对应到屏幕的像素点,比如iphone3GS是320*480的屏,逻辑点是默认的320*480,而iphone4/S的Retina屏是640*960,开启支持RetinaDisplay的情况下逻辑点依然320*480,但每个点对应2*2的屏幕像素点,官方教程:http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:how_to_develop_retinadisplay_games_in_cocos2d?s

 

 

2.3注意事项

 

#1.使用该方案需要用到两套图:

u  一套为SD标清图,以320*480像素为基准,即iphone3GS的分辨率。

u  一套为HD高清图,图片命名与SD图相同,但有 –hd 后缀,以640*960像素为基准,即iphone4/S的分辨率。

//两套图需要同时放入相同路径下,否则可能出现资源匹配出错

 

#2.因为使用了两套图,所以会增加很多的安装包容量以及内存占用量(-hd模式时),因此要求所有分类资源都尽量放到若干个图片集中,可以使用拼图工具TexturePacker、Zwoptex(仅Mac)等来实现,在项目中尽量多使用CCSpriteBatchNode等集合节点能大大优化内存使用和效率;另外使用Texture Packer这类工具还可以自动生成cocos2d支持的.plist 配置文件,在项目中使用CCFrameCache能够快捷调用图集中的子图,这种方法也被用于创建帧动画。

 

#3.程序中并不需要在调用资源时额外给予-hd后缀,以上的方法会自动判断是否高清模式,若是高清模式则会根据给的图片名(不带-hd)自动匹配带-hd的资源

 

#4.不仅图片文件要有-hd后缀,其他例如.plist文件等同样需要带-hd后缀和不带后缀两套资源。声音文件待验证!

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值