原创作品,转载请标明:http://blog.youkuaiyun.com/jackystudio/article/details/12610287
cocos2d-x到底是怎样实现跨平台的呢?这里以Win32和Android为例。
1.跨平台项目目录结构
先看一下一个项目创建后的目录结构吧!这还是以HelloCpp为例。
从左边目录可以看到,Classes和Resource已经平台无关了,而Classes中包含了AppDelegate类,因此我们可以认为AppDelegate是与平台最接近的类,在它以上就要区分平台了。
2.Win32下的实现
在前一篇就介绍了Win32怎么开始cocos2dx,Win32平台下main.cpp就是程序入口:
- intAPIENTRY_tWinMain(HINSTANCEhInstance,
- HINSTANCEhPrevInstance,
- LPTSTRlpCmdLine,
- intnCmdShow)
- {
- UNREFERENCED_PARAMETER(hPrevInstance);
- UNREFERENCED_PARAMETER(lpCmdLine);
- //createtheapplicationinstance
- AppDelegateapp;//创建应用实例
- CCEGLView*eglView=CCEGLView::sharedOpenGLView();
- eglView->setViewName("HelloCpp");
- eglView->setFrameSize(2048,1536);
- eglView->setFrameZoomFactor(0.4f);
- returnCCApplication::sharedApplication()->run();//运行程序
- }
3.Android下的实现
3.1.cocos2d-x程序入口
我们先看一下Android下cocos2d-x程序入口点在哪,我们知道Android是采用Java编写的,而cocos2d-x是c++编写的,所以如果要在Java中调用c++代码,那就需要采用JNI技术,看起来好像高端大气上档次,其实程序就是函数调用,也就是输入→处理→输出,所以JNI实际上简单抽象出来就这么回事:
- java输入→Jni→c++输入→c++处理(API实现)→c++输出→Jni→java输出
- jintJNI_OnLoad(JavaVM*vm,void*reserved)
- {
- JniHelper::setJavaVM(vm);
- returnJNI_VERSION_1_4;
- }
- voidJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv*env,jobjectthiz,jintw,jinth)
- {
- if(!CCDirector::sharedDirector()->getOpenGLView())
- {
- CCEGLView*view=CCEGLView::sharedOpenGLView();
- view->setFrameSize(w,h);
- AppDelegate*pAppDelegate=newAppDelegate();
- CCApplication::sharedApplication()->run();
- }
- else
- {
- ccGLInvalidateStateCache();
- CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
- ccDrawInit();
- CCTextureCache::reloadAllTextures();
- CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_FOREGROUND,NULL);
- CCDirector::sharedDirector()->setGLDefaultValues();
- }
- }
里面包含了2个函数,JNI_OnLoad和Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit。我们看一下功能而先不管它在哪里被调用。
(1)JNI_OnLoad,这个函数主要是用来高速Android VM当前使用的是什么版本是Jni,如果不提供此函数,则默认使用Jni1.1版本。
(2)Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit,这个函数很明显就是运行一个cocos2d-x的应用实例了,这和Win32是一样的,当然它多了一个openGlView的检测。一旦调用了它那么cocos2d-x游戏启动。
接下来再看看它们是在哪里被调用的。
3.2.JNI_OnLoad的调用
在proj.android\src\org\cocos2dx\hellocpp目录下,可以看到Android的入口Activity,也就是HelloCpp,它继承自Cocos2dxActivity。
- publicclassHelloCppextendsCocos2dxActivity{
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- }
- static{
- System.loadLibrary("hellocpp");
- }
- }
3.3.Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit的调用
那最重要的Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit是在哪调用呢?这就比较麻烦了,先大致了解一下Cocos2dxActivity做了一些什么事。
直接进入Cocos2dxActivity的OnCreate函数,它调用了一个init初始化函数:
- publicvoidinit(){
- //设置布局,是一个FrameLayout
- ViewGroup.LayoutParamsframelayout_params=
- newViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.FILL_PARENT);
- FrameLayoutframelayout=newFrameLayout(this);
- framelayout.setLayoutParams(framelayout_params);
- //设置Cocos2dxEditText布局,这一个跟GLSurfaceView兼容的edittext
- ViewGroup.LayoutParamsedittext_layout_params=
- newViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- Cocos2dxEditTextedittext=newCocos2dxEditText(this);
- edittext.setLayoutParams(edittext_layout_params);
- //添加到framelaout
- framelayout.addView(edittext);
- //创建Cocos2dxGLSurfaceView
- this.mGLSurfaceView=this.onCreateView();
- //添加到framelaout
- framelayout.addView(this.mGLSurfaceView);
- //SwitchtosupportedOpenGL(ARGB888)modeonemulator
- if(isAndroidEmulator())
- this.mGLSurfaceView.setEGLConfigChooser(8,8,8,8,16,0);
- //设置Cocos2dxRenderer和Cocos2dxEditText
- this.mGLSurfaceView.setCocos2dxRenderer(newCocos2dxRenderer());
- this.mGLSurfaceView.setCocos2dxEditText(edittext);
- //设置framelayout作为内容视图
- setContentView(framelayout);
- }
在这里Cocos2dxActivity做的就是创建Cocos2dxGLSurfaceView,并设置了Cocos2dxRenderer和Cocos2dxEditText,然后添加到FramLayout。具体的各部分实现这里就不贴代码了,画了个图: