cocos2dx3.2项目移植andriod总结

来源:互联网 发布:淘宝炫舞摘花 编辑:程序博客网 时间:2024/05/14 06:09

大渣好,我是PuzzledBoy,今年大一,我是一名独立游戏开发者。这是我的第二篇博客,欢迎你们的来袭。。。(这话有点不对啊= =)

额,总之这会是一篇比较长的文章,总结一下我前两天将cocos2dx3.2 项目移植到渣卓平台出现的各种问题(我恨渣卓)。

一来是相当于自己复习一下酱紫,而来就是写给你们看啦啦啦~(废话)。

当然也会说一点其他的内容,就算你和标题没有任何关系(好像有语病。。。)也是可以往下看的,说不定会学到一点其他的东西。呵呵呵呵呵。。。。。


首先第一个部分是把C++工程打包成apk

//============================================================================渣卓黑分隔线=============================================================================


首先呢,C++ 工程移植到渣卓,哦不,安卓平台= =。 当然是要跟android ndk扯上一点关系了,详细的介绍度娘说的很清楚了 博主就懒得再复制黏贴了。咳咳。。。

哎这里先说一下几个概念...

.o 目标文件,相当与window下的.obj文件。

.so (shared object) 共享库,相当于window下的dll。

.a 静态库,用于静态链接,相当于windoiw的静态lib了。

其实概念跟windos上是相同的,不知道windows上的静态库和动态库是什么的童鞋去问度娘吧。

然后,博主的项目用到了第三方库(lua)(不是引擎官方的那个lua,我只是纯粹用lua来做配置文件),酱紫就有个问题了,如果没有引入第三方库的话,我们可以直接更改Android.mk文件的配置信息然后用命令行来进行android打包。


首先我们打开Android.mk文件,路径是 “ 你的工程目录/proj.android/jni/Android.mk "

这是一个脚本文件,先别急着说看不懂。首先mk文件是用来向android ndk描述你的C++源代码的。其次我们来聊一下里面几个关键字的意义(详细的结构由于篇幅就不复制度娘的了,可以自己去查)。

LOCAL_PATH := $(call my-dir)  //call my-dir就是你的mk文件所在的目录。include $(CLEAR_VARS) //这里是清除一些全局变量。$(call import-add-path,$(LOCAL_PATH)/../../cocos2d)$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)  //你可以打开到相应的文件夹去看看,里面有一个Android.mk文件耶                                                            //好了,你一定懂了这里的路径是用来干吗了的吧 = =。LOCAL_MODULE := cocos2dcpp_shared //模块类型,这里是共享库。LOCAL_MODULE_FILENAME := libcocos2dcpp // 模块的名字。LOCAL_SRC_FILES := hellocpp/main.cpp \                   ../../Classes/AppDelegate.cpp \                        # 省略了很多代码          //这里是用来描述你的cpp文件的,写上你的cpp路径就好啦。 LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../cocos2d  //顾名思义,就是头文件的目录啦。LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_staticLOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static # LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static# LOCAL_WHOLE_STATIC_LIBRARIES += cocosbuilder_static# LOCAL_WHOLE_STATIC_LIBRARIES += spine_static# LOCAL_WHOLE_STATIC_LIBRARIES += cocostudio_static# LOCAL_WHOLE_STATIC_LIBRARIES += cocos_network_static# LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static   //这里指明的是当前模块需要依赖的模块名称,static表明是静态库。include $(BUILD_SHARED_LIBRARY) //这相当于一个命令,编译成共享库。$(call import-module,.)$(call import-module,audio/android)# $(call import-module,Box2D)# $(call import-module,editor-support/cocosbuilder)# $(call import-module,editor-support/spine)# $(call import-module,editor-support/cocostudio)# $(call import-module,network)# $(call import-module,extensions)   //其他模块的路径。 对了,当要在项目中需要用到指定模块的时候取消掉前面的注释# 就好啦。

好了,问题是,博主的项目用了第三方的动态库,那么这个mk文件要怎么写呢?你问窝?疑问  窝母鸡啊。。。窝是真的母鸡= =,虽然我觉得肯定是可以通过某种办法调用dll库的,但是嘛,鉴于博主的才刚念完大一,很多知识都不懂额(装个嫩先可怜)。 经过多次百度无果后,我换了一个思路。。。

我们来模仿cocos2dx 官方demo,将我们的第三方源码编译成静态库项目,然后学着demo编写一份mk文件,然后。。。。。。

首先窝们来创建一个静态库工程,用的IDE是Visual Studio 2013 ,其他大同小异。把一堆源代码复制黏贴之后,编译成静态库,如图(哎呀这个比例是怎么回事= =)


额,不要在意这种细节,窝们继续。。。

然后设置项目引用 ~~巴拉巴拉~~之类的~~ 

哦对了,补充一下,编译静态库的时候遇到很多个类似的错误:

错误    1    error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\lvm.c    53    1    libLua
错误    2    error C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\luac.c    43    1    libLua
错误    3    error C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\lua.c    425    1    libLua
错误    4    error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\lstrlib.c    845    1    libLua
错误    5    error C4996: 'tmpnam': This function or variable may be unsafe. Consider using tmpnam_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\loslib.c    108    1    libLua
错误    6    error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\lobject.c    209    1    libLua
错误    7    error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\loadlib.c    331    1    libLua
错误    8    error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\liolib.c    220    1    libLua
错误    9    error C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.    f:\snrs\liblua\lua\lauxlib.c    216    1    libLua

因为微软觉得C语言的某些函数并不安全(没有进行类型检查什么的),所以提供了一个更安全的版本。我们可以根据错误提示把错误的函数换掉就好了,当然,因为换的时候还要改动一些其他的代码而且错误也很多,我们就用第二种方法,项目->属性->C/C++/命令行->/其他选项 添加下面的命令  /D "_CRT_SECURE_NO_DEPRECATE"
然后再次编译,成功。


好了,窝们模仿其他静态库工程目录下的mk文件,自己复制一份过来,然后把内容修改成下面酱紫:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := lua_staticLOCAL_MODULE_FILENAME := libluaLOCAL_SRC_FILES := \ //省略很多代码,你的cpp文件路径 LOCAL_C_INCLUDES := $(LOCAL_PATH)/luainclude $(BUILD_STATIC_LIBRARY)

好了,然后窝们在回到一开始打开的那个mk文件(就是上面的上面那个),窝们的lua静态库项目的根目录是 ” 你的项目目录/libLua “

然后在”相应位置“分别写入以下内容

$(call import-add-path,$(LOCAL_PATH)/../../libLua)LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../libLuaLOCAL_WHOLE_STATIC_LIBRARIES += lua_static$(call import-module,../../libLua)

额,相应位置,就是你看到哪里类似的加到他后面就行了。= =

好了,然后窝们来运行一下命令行(我擦这图片怎么突然这么大!!! = =)



咳咳咳,不要在意这种细节,窝们注意一下error 报错的信息。 找不到成员???啥子个情况。窝们打开相应头文件,发现struct lconv 是在<locale.h> 里面定义,这是一个vc的源代码,找到struct lconv的定义:

struct lconv {
char *decimal_point;
char *thousands_sep;
char *grouping;
char *int_curr_symbol;
char *currency_symbol;
char *mon_decimal_point;
char *mon_thousands_sep;
char *mon_grouping;
char *positive_sign;
char *negative_sign;
char int_frac_digits;
char frac_digits;
char p_cs_precedes;
char p_sep_by_space;
char n_cs_precedes;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
wchar_t *_W_decimal_point;
wchar_t *_W_thousands_sep;
wchar_t *_W_int_curr_symbol;
wchar_t *_W_currency_symbol;
wchar_t *_W_mon_decimal_point;
wchar_t *_W_mon_thousands_sep;
wchar_t *_W_positive_sign;
wchar_t *_W_negative_sign;
};

放在源码里面真是看不懂,但是第一个就是decimal_point 成员嘛,怎么编译说找不到成员呢?

一开始以为是vc或者ndk版本的问题,换了很多个版本还是不行啊。

经过很久的排除,博主发现自己傻了,ndk用的是自己的<locale.h>,而不是vc的<locale.h> = =,汗找了很久问了很多人。

然后窝们打开ndk里面相应的头文件 路径:

发现里面的定义是这样 struct lconv { } ; 没有任何成员,难怪会报错误了。

不过,这让博主很头疼啊,这种源代码对我这种渣渣小白来说都是神圣不可侵犯的,为什么这里的定义跟vc的不同?难道是ndk源代码的bug?纠结了很久,想想还是改动ndk的源代码试试,不过先做了备份= =。

改成了这样

struct lconv {
char *decimal_point;
char *thousands_sep;
char *grouping;
char *int_curr_symbol;
char *currency_symbol;
char *mon_decimal_point;
char *mon_thousands_sep;
char *mon_grouping;
char *positive_sign;
char *negative_sign;
char int_frac_digits;
char frac_digits;
char p_cs_precedes;
char p_sep_by_space;
char n_cs_precedes;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
};

wchar* 类型找不到的所以去掉了,反正有第一个成员就行了吧= =,先试试。

保存编译,成功!!!

哈哈哈我发现android ndk的bug了。 后来发现ndk里面有好多个<locale.h>,struct lconv的定义也有些不同,所以我晕了= =,Orz,到底是ndk的问题还是lua的问题还是其他问题呢?


不管怎么说这个bug找了我好久最终修改ndk源代码编译成功了!

好了,接下来我们来在虚拟机上运行看看吧。 那么进入下一部分了。


//=======================================================================渣卓纯黑分隔线================================================================================

恩,我们在虚拟机上运行apk,然后”闪退”了! OMG!!

经过努力的查找,最后发现原来是安卓使用lua dofile的时候路径跟win32的不同啊= =。


怎么办= =,怎么改寻找路径?这个我真不知道百度也找不到= =Orz。。。

后来问度娘问出了另一个方法,我们用先把文件读取到字符串中(读取方式很多,可以用C++的文件流,可以用引擎的提供的文件读取借口,总之只要能把文件的内容保存到字符串就行了),然后用lua dostring来执行。

修改代码之后,再次编译运行到虚拟机,这下可以了= =。

哦对了,lua dofile的时候 # 开头的那一行是会被忽略的,但是将文件读取到字符串之后再 lua dostring 就会报错,坑,囧。


运行是可以了,不过又发现一个问题,

win32下:         

渣卓虚拟机下:


哭瞎

好像是屏幕适配的问题。cocos2dx 的屏幕适配方案可以参考这里:http://or7rccl.blog.163.com/blog/static/70836367201401314947502/

这里解释一下三个分辨率的意思(刚开始没搞懂):

资源分辨率:就是你的资源图像的分辨率啦。

设计分辨率:就是你设计游戏时候参考的分辨率。setDesignResolutionSize 传入的参数就是设计分辨率的大小。

屏幕分辨率:就是你的设备的分辨率,在win32下通过setframSize来设置。


不过我敢肯定我确实是按照那个方案来的,采取的是FixExcel的适配方式。

但是!!!在win32里面不管怎么改分辨率都可以完美适配,一运行到虚拟器上就不行。

后来发现tm的是虚拟器的问题(BlueStack),坑啊啊啊啊啊啊啊,经朋友推荐换了”靠谱助手“,恩真的挺靠谱的,相同代码和win32的一样完美适应了。


好了,这下可以在虚拟机运行,屏幕适配也没问题。但是又遇到一个坑的问题,程序一直运行到某个地方就闪退了。

经过排除查找,发现只要使用cocos2d::extention::ControlSlider这个类,就是会闪退。这是真的坑

后来果断用cocos2d::ui::uiSlider代替,好了不闪退了= =。


由于博主用的是苹果嘛(还是我大苹果好)==,所以程序只能在虚拟器上运行,目前好像没问题了。

然后发apk给同学的 真·渣卓机运行:


然后发现只要涉及到cocos2d::ui::ScrollView这个类,全部都是出现不明觉厉的绿色。貌似是剪裁和渲染出了问题。

后来找到一篇参考文章:http://www.cocoachina.com/bbs/read.php?tid=195955&page=1

再后来,打开AppActivity.java,路径如下


修改java代码:

public class AppActivity extends Cocos2dxActivity { public Cocos2dxGLSurfaceView onCreateView() {         Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);         glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);         return glSurfaceView; }}

别忘了在开头加上这个
package org.cocos2dx.cpp;

再次运行到真机上,终于可以了,Orz。。。


好了,暂时是整理了这么多这几天移植出现的一些问题。


补充2014.09.01 :

又发现一个坑爹问题,在win32下,资源路径的大小写是自适应的,但在android下是严格匹配的。

例如你有一张资源图片Path.png,在程序中读取路径写成path.png。 这个在win32下运行没问题,程序帮你做转化了,但是在android下,这样的差异会导致闪退!!!

所以,大家要保持好的编程习惯啊Orz...


补充2014.09.02 :
Orz我又来了,今天又发现一个问题。。。

Android对asserts里面的资源文件是只能读不能写的(好吧我没用过安卓机大神勿喷)。

在win32下,Resource文件夹里面的文件是可以自由读写的。So...

好了不废话了,怎么搞!!!

经过在虚拟机上运行官方Demo,我发现我们可以用我们可以用cocos2d::fileutils->getWritablePath();获取完整的可写入路径。(是不是有语病?忘记了。。。

在win32下,返回的路径是 “你的工程目录/proj.win32/Debug.win32/”。

在android下,返回的路径是 “/data/data/你的android包/files/”。

andoird的那个路径,具体没用过也不清楚在哪里,应该是SD卡之类的地方吧= =。

所以,我们写跨平台代码的时候,要用cocos2d::fileutils->getWritablePath()获取写入路径,然后在把文件内容写进去。。。

两大平台的差异,真是搞的我好苦啊。。。


还有一个问题,我们编译成release版本的apk的时候,直接装没用,要签名什么的。

签名这东西我查了很多资料,因为没有配置eclipse,所以我用java jdk 命令行来生成密匙再进行签名。

可是试了很多次再装apk还是不行。Orz。。。搞的我只能发布debug版本的apk了......
哪个大神知道也可以留个言什么的


这是PuzzledBoy的第一篇博客,后续可能会将我的一些学习笔记整理并发布到博客上。谢谢你的阅读和关注咯~~~~~~


0 0
原创粉丝点击