Cocos2d-x 3.3为Android平台提供的封装

proj.android分析

AndroidManifest.xml

1. use opengl es 2.0

1
<uses-feature android:glEsVersion= "0x00020000"  />

2. 问题1,在哪里用到的这个so?

1
2
3
<!-- Tell Cocos2dxActivity the name of our .so -->
         <meta-data android:name= "android.app.lib_name"
                    android:value= "cpp_empty_test"  />

3. 支持的屏幕尺寸

1
2
3
4
5
<supports-screens android:anyDensity= "true"
                   android:smallScreens= "true"
                   android:normalScreens= "true"
                   android:largeScreens= "true"
                   android:xlargeScreens= "true" />


assets目录

从Resources拷贝的资源


jni目录

除了make file外, 有个main.cpp, 内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//log相关
#define  LOG_TAG    "main"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
 
using  namespace  cocos2d;
 
//看起来怪怪的,new了一个AppDelegate之后,就不管了
//对比linux平台的,至少还调用了run方法
 
//问题2,谁调用的这个方法?
void  cocos_android_app_init (JNIEnv* env, jobject thiz) {
     LOGD( "cocos_android_app_init" );
     AppDelegate *pAppDelegate =  new  AppDelegate();
}


libs目录

由于我编译了,这个目录下有对应ABI的so。


src目录

AppActivity 代码如下

1
2
3
//看样子,料全在基类了
public  class  AppActivity extends Cocos2dxActivity {
}


小结下proj.android

留了两个问题待解答,详见下文。


Cocos2d-x针对Android平台的封装

cocos/platform/android/目录下都有什么

  • ControllerManualAdapter //粗略过了下代码,和游戏手柄相关,略

  • java代码

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
37
38
39
40
41
42
43
44
45
46
47
48
//android加速度传感器事件对接。注册监听器后,android产生相应事件并
//回调到Cocos2dxAccelerometer的onSensorChanged再经过
//Cocos2dxGLSurfaceView.queueAccelerometer(x,y,z,sensorEvent.timestamp);
//之后调用到Cocos2dxAccelerometer的本地方法onSensorChanged
//该方法所在位置Java_org_cocos2dx_lib_Cocos2dxAccelerometer.cpp,
//该方法在native层dispatchEvent一个传感器事件
Cocos2dxAccelerometer.java
//java层的图片工具类,简单跟了下代码,调用方向是从native方法调用到java层
Cocos2dxBitmap.java
//自定义了一个编辑对话框,对输入类型,键盘显示隐藏等做了些包装
Cocos2dxEditBoxDialog.java
//自定义编辑框,特殊处理了back按键
Cocos2dxEditText.java
//自定义handler,主要和弹出对话框相关
Cocos2dxHandler.java
//工具类,UserDefault存储相关的jni调用,获取包名,终止进程等
//主要调用方向是native到java
Cocos2dxHelper.java
//数据库存储,主要供native端调用到java
Cocos2dxLocalStorage.java
//lua相关
Cocos2dxLuaJavaBridge.java
//java层的音乐播放相关,包装的MediaPlayer,用来播放长的音乐等
//主要由Cocos2dxHandler.java调用过来
//看样子音乐播放这块多半就是用的java层的播放器了
Cocos2dxMusic.java
//java层的音乐播放相关,包装的用soundpool,
//用来播一些短的反应速度要求高的音效
Cocos2dxSound.java
//输入事件监听相关,配合Cocos2dxGLSurfaceView的工作
Cocos2dxTextInputWraper.java
//Typeface cache相关
Cocos2dxTypefaces.java
//android视频播放器,MediaPlayer+SurfaceView
//对应的helper用来将videoview从父控件动态添加删除,简化调用等
Cocos2dxVideoView.java
Cocos2dxVideoHelper.java
//自定义webview,类似上面的视频播放器的封装
Cocos2dxWebView.java
Cocos2dxWebViewHelper.java
//游戏手柄相关
GameControllerAdapter.java
GameControllerDelegate.java
GameControllerUtils.java
//放后面一起看TODO
Cocos2dxActivity.java
Cocos2dxRenderer.java
Cocos2dxGLSurfaceView.java
  • cpp

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
37
//application 在android平台相关的实现,跨平台实现细节,针对平台的具体实现
CCApplication-android.cpp
CCApplication-android.h
//native层的工具类,通过jni调用到java层弹框等
CCCommon-android.cpp
//native层的工具类,获取dpi,设置加速监听器,图片处理等
CCDevice-android.cpp
//fileUtils的android平台相关的实现,类似application了
CCFileUtils-android.cpp
CCFileUtils-android.h
//一堆和opengl相关的宏等
CCGL-android.h
//glview android平台的相关实现,类似application了
CCGLViewImpl-android.cpp
CCGLViewImpl-android.h
//一些宏定义
CCPlatformDefine-android.h
CCStdC-android.h
//放后面一起看TODO
javaactivity-android.cpp
//各种jni相关的helper类或者方法
//提一提touchesJni.cpp,他是用来对接android touch事件和key事件的
//和上面的加速器事件一样的逻辑, 稍后看具体的事件源头
DPIJni.cpp
DPIJni.h
IMEJni.cpp
IMEJni.h
Java_org_cocos2dx_lib_Cocos2dxAccelerometer.cpp
Java_org_cocos2dx_lib_Cocos2dxBitmap.cpp
Java_org_cocos2dx_lib_Cocos2dxBitmap.h
Java_org_cocos2dx_lib_Cocos2dxHelper.cpp
Java_org_cocos2dx_lib_Cocos2dxHelper.h
Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp
JniHelper.cpp
JniHelper.h
TouchesJni.cpp

上面一些非重点的代码java的C++的,我们都过了一遍,涉及的内容都和jni相关包括事件源头的对接,各种跨平台实现细节和输入弹框等。重点代码则是上面的几个标记为TODO的相关类, 接下来重点分析:

A. Cocos2dxActivity.java

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
1. oncreate
     @Override
     protected  void  onCreate(final Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
//这里问题1的得到解答
//在manifest中配置的元数据信息,so库的名称
//该库在这里得到了加载
         onLoadNativeLibraries();
         sContext =  this ;
         this .mHandler =  new  Cocos2dxHandler( this );
//helper和这个activity绑定了
         Cocos2dxHelper.init( this );
//这里问题2得到解答
//这个native方法的调用过程中
//调用了 cocos_android_app_init(env, thiz);初始化了一个applicaton
         this .mGLContextAttrs = getGLContextAttrs();
//初始化,下面细看
         this .init();
//接下来的两个helper用来动态往mFrameLayout中添加或删除相应的view
         if  (mVideoHelper == null) {
             mVideoHelper =  new  Cocos2dxVideoHelper( this , mFrameLayout);
         }
         if (mWebViewHelper == null){
             mWebViewHelper =  new  Cocos2dxWebViewHelper(mFrameLayout);
         }
     }
 
2. init
    public  void  init() {
//创建父容器FrameLayout
         // FrameLayout
         ViewGroup.LayoutParams framelayout_params =
             new  ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                        ViewGroup.LayoutParams.MATCH_PARENT);
         mFrameLayout =  new  FrameLayout( this );
         mFrameLayout.setLayoutParams(framelayout_params);
//添加了一个编辑框,但是是干嘛用的?问题3
         // Cocos2dxEditText layout
         ViewGroup.LayoutParams edittext_layout_params =
             new  ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                        ViewGroup.LayoutParams.WRAP_CONTENT);
         Cocos2dxEditText edittext =  new  Cocos2dxEditText( this );
         edittext.setLayoutParams(edittext_layout_params);
         // ...add to FrameLayout
         mFrameLayout.addView(edittext);
//添加一个glSurfaceView到容器
         // Cocos2dxGLSurfaceView
         this .mGLSurfaceView =  this .onCreateView();
         // ...add to FrameLayout
         mFrameLayout.addView( this .mGLSurfaceView);
         // Switch to supported OpenGL (ARGB888) mode on emulator
         if  (isAndroidEmulator())
            this .mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
//设置glSurfaceView的render
         this .mGLSurfaceView.setCocos2dxRenderer( new  Cocos2dxRenderer());
         this .mGLSurfaceView.setCocos2dxEditText(edittext);
//通过activity展现出来
         // Set framelayout as the content view
         setContentView(mFrameLayout);
     }


B. Cocos2dxGLSurfaceView.java

1
2
3
4
5
//这个类的代码就不贴了, 不过看了之后应该一些疑惑就得到了解答
//加速器事件,touch事件,key事件的分发都从这里继续派发
//输入法的弹出或者关闭处理也在这里,这里解答了问题3,用那个编辑框来做输入法弹出相关的逻辑
//因为InputMethodManager的showSoftInput,hideSoftInputFromWindow需要相应的参数
//同时,注意这点在onResume时设置的renderMode, setRenderMode(RENDERMODE_CONTINUOUSLY);

C. Cocos2dxRenderer.java

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
37
38
39
40
41
42
43
44
45
//这个类关注几个callback就好
1. onSurfaceCreated
这里调用了一个本地方法nativeInit, 负责给导演设置了glview并调用了application的run方法
联想到linux的实现,看样子android的大循环也开启了, 但令人感到奇怪的是,android的application
的run方法只调用了applicationDidFinishLaunching而没哟类似linux的大循环。。。问题4
吼吼,继续走起
2. onSurfaceChanged
//屏幕方向变化等导致的回调
3. onDrawFrame
     @Override
     public  void  onDrawFrame(final GL10 gl) {
         /*
          * No need to use algorithm in default(60 FPS) situation,
          * since onDrawFrame() was called by system 60 times per second by default.
          */
//android本身是一秒种onDrawFrame才被调用60次,
//也就是fps大于等于60次的都按fps=60来算了,高了也做不到,受限于onDrawFrame这个方法了
         if  (sAnimationInterval <= 1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND) {
             Cocos2dxRenderer.nativeRender();
         else  {
//fps小于60的情况
             final  long  now = System.nanoTime();
             final  long  interval = now -  this .mLastTickInNanoSeconds;
             if  (interval < Cocos2dxRenderer.sAnimationInterval) {
                 try  {
                     Thread.sleep((Cocos2dxRenderer.sAnimationInterval - interval) / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND);
                 catch  (final Exception e) {
                 }
             }
             /*
              * Render time MUST be counted in, or the FPS will slower than appointed.
             */
             this .mLastTickInNanoSeconds = System.nanoTime();
             Cocos2dxRenderer.nativeRender();
         }
     }
     
4. Cocos2dxRenderer.nativeRender
     JNIEXPORT  void  JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) {
         cocos2d::Director::getInstance()->mainLoop();
     }
//豁然开朗
//onDrawFrame相当于一个循环了,mainLoop在这个循环中被调用
//逻辑本质上和linux的分析是一样的
//问题4得到解答

D. javaactivity-android.cpp

1
//在上面的分析中这个文件已经都涉及到了


小结

  • 在proj.androd工程里面,几个注意的细节:manifest里面定义了so库的名称并在cocos提供的Cocos2dxActivity onCreate里得到加载;jni里面的main.cpp里面有个奇怪的方法并在那里new了一个application对象,而这个方法同样是被Cocos2dxActivity onCreate方法间接调用到的。

  • 在目录cocos/platform/android/下,有用信息很丰富,包含了:

  • 很多跨平台实现细节里面的关于android平台的特地实现,如application, fileUtil, glView等

  • 对接android平台的事件源,在java层设置事件监听,监听器被回调,jni调用到native层,native层通过事件分发器发送事件。这个过程基本都和glSurfaceView关联了。这里的事件包括加速器事件,touch事件,key事件。

  • 对比linux平台的那个大循环,android的大循环本质思路还是一样的。只是那个大循环被Cocos2dxRenderer.java onDrawFrame代替。关于glSurfaceView GLSurfaceView.Renderer的更多信息请参考扩展阅读里面的链接。

  • 提供了android平台上关于音频播放相关的两个封装。而且是供native方法调用的。具体用法暂没细看。

  • 提供了android平台上播放视频和打开网页相关的分装,通过动态往Cocos2dxActivity的contentView里面添加删除videoView或者webView来实现。具体用法暂没细看。

  • 提供了本地数据库存储的包装实现。

  • 提供了很多helper类或者功能,弹出对话框,弹出输入法框,获取应用包名等。

  • 提一提android程序是怎么退出的:menuCloseCallback --> Director::getInstance()->end() --> (android平台的实现)GLViewImpl::end() --> (Java_org_cocos2dx_lib_Cocos2dxHelper.cpp)terminateProcessJNI --> (Cocos2dxHelper.java) terminateProcess --> android.os.Process.killProcess(android.os.Process.myPid());

  • 那android程序怎么起来的呢。。。Zygote and fork, that's a long story

  • 看这部分代码有个细节要注意,这里涉及到jni,但jni也没那么可怕,记住调用方向就好,java调用c++的方法时该方法要用native修饰,c++调用java一般是通过jnihelper来调用java层的xxHelper的static方法。

  • 关于在Cocos2dxActivity contenView里面有一个隐藏的Cocos2dxEditText这里应该还有不少故事。


扩展阅读

http://developer.android.com/reference/android/opengl/GLSurfaceView.html

http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html

OpenGL例子:https://github.com/cheyiliu/test4opengles

http://developer.android.com/training/articles/perf-jni.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值