【玩转cocos2d-x之四】cocos2d-x怎么实现跨平台

cocos2d-x到底是怎样实现跨平台的呢?这里以Win32和Android为例。

跨平台项目目录结构

先看一下一个项目创建后的目录结构吧!这还是以HelloCpp为例。



从左边目录可以看到,Classes和Resource已经平台无关了,而Classes中包含了AppDelegate类,因此我们可以认为AppDelegate是与平台最接近的类,在它以上就要区分平台了。

Win32下的实现

在前一篇就介绍了Win32怎么开始cocos2dx,Win32平台下main.cpp就是程序入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int APIENTRY _tWinMain(HINSTANCE hInstance,  
HINSTANCE hPrevInstance,
LPTSTRlpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// create the application instance
AppDelegate app;//创建应用实例
CCEGLView* eglView = CCEGLView::sharedOpenGLView();
eglView->setViewName("HelloCpp");
eglView->setFrameSize(2048, 1536);
eglView->setFrameZoomFactor(0.4f);
return CCApplication::sharedApplication()->run();//运行程序
}

Win32下的实现比较简单,就是正常的创建实例,运行就可以了。

Android下的实现

cocos2d-x程序入口

我们先看一下Android下cocos2d-x程序入口点在哪,我们知道Android是采用Java编写的,而cocos2d-x是c++编写的,所以如果要在Java中调用c++代码,那就需要采用JNI技术,看起来好像高端大气上档次,其实程序就是函数调用,也就是输入→处理→输出,所以JNI实际上简单抽象出来就这么回事:

java输入→Jni→c++输入→c++处理(API实现)→c++输出→Jni→java输出

在\proj.android\jni\hellocpp文件夹下可以找到main.cpp,这就是cocos2d-x的入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
jint JNI_OnLoad(JavaVM *vm, void *reserved)  
{

JniHelper::setJavaVM(vm);

return JNI_VERSION_1_4;
}

void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h)
{

if (!CCDirector::sharedDirector()->getOpenGLView())
{
CCEGLView *view = CCEGLView::sharedOpenGLView();
view->setFrameSize(w, h);

AppDelegate *pAppDelegate = new AppDelegate();
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游戏启动。
接下来再看看它们是在哪里被调用的。

JNI_OnLoad的调用

在proj.android\src\org\cocos2dx\hellocpp目录下,可以看到Android的入口Activity,也就是HelloCpp,它继承自Cocos2dxActivity。

1
2
3
4
5
6
7
8
9
10
public class HelloCpp extends Cocos2dxActivity{  

protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}

static {
System.loadLibrary("hellocpp");
}
}

很简单的代码,因为功能都被封装到Cocos2dxActivity中了,所以OnCreate中调用了父类的OnCreate就把功能都实现了,而system.LoadLibrary就是载入编译出来的.so文件,此时就会执行JNI_OnLoad。

Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit的调用

那最重要的Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit是在哪调用呢?这就比较麻烦了,先大致了解一下Cocos2dxActivity做了一些什么事。

直接进入Cocos2dxActivity的OnCreate函数,它调用了一个init初始化函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public void init() {  

// 设置布局,是一个FrameLayout
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
FrameLayout framelayout = new FrameLayout(this);
framelayout.setLayoutParams(framelayout_params);

// 设置Cocos2dxEditText布局,这一个跟GLSurfaceView兼容的edittext
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Cocos2dxEditText edittext = new Cocos2dxEditText(this);
edittext.setLayoutParams(edittext_layout_params);

// 添加到framelaout
framelayout.addView(edittext);

// 创建Cocos2dxGLSurfaceView
this.mGLSurfaceView = this.onCreateView();

// 添加到framelaout
framelayout.addView(this.mGLSurfaceView);

// Switch to supported OpenGL (ARGB888) mode on emulator
if (isAndroidEmulator())
this.mGLSurfaceView.setEGLConfigChooser(8 , 8, 8, 8, 16, 0);

//设置Cocos2dxRenderer和Cocos2dxEditText
this.mGLSurfaceView.setCocos2dxRenderer(new Cocos2dxRenderer());
this.mGLSurfaceView.setCocos2dxEditText(edittext);

// 设置framelayout作为内容视图
setContentView(framelayout);
}

在这里Cocos2dxActivity做的就是创建Cocos2dxGLSurfaceView,并设置了Cocos2dxRenderer和Cocos2dxEditText,然后添加到FramLayout。具体的各部分实现这里就不贴代码了,画了个图:



好了,就这样吧。因为我对Android界面开发,特别是OpenGLView这块也不熟,所以只能大概推出是这样子了,有什么错误,还请指出。

文章目录
  1. 1. 跨平台项目目录结构
  2. 2. Win32下的实现
  3. 3. Android下的实现
    1. 3.1. cocos2d-x程序入口
    2. 3.2. JNI_OnLoad的调用
    3. 3.3. Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit的调用
,