1. NativeActivity透明处理
总共有以下两层,下层为Video层(SurfaceView),上层为3D OpenGL层(View),Video全屏显示,3D无图形元素的地方透明,即可以看到下层的视频。
1.1 项目中的Cocos2dxActivity.java
其主要功能为:1) 向Activity中增加一个SurfaceView,并使3D OpenGL层(View)位于最上面。
2) 播放视频
其完整原代码如下所示:
package org.cocos2dx.cpp; import android.app.NativeActivity; import android.app.Activity; import android.graphics.PixelFormat; import android.media.MediaPlayer; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.view.View.OnClickListener; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.view.ViewGroup; import java.io.IOException; public class Cocos2dxActivity extends NativeActivity{ private static final String TAG="MyGame"; private SurfaceView mediaPlayView; private SurfaceHolder mediaSurfaceHolder = null; private MediaPlayer mediaPlayer; private boolean isMediaPlay = false; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); Log.d(TAG,"onCreate start..."); mediaPlayView = new SurfaceView(this); mediaSurfaceHolder = mediaPlayView.getHolder(); mediaSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mediaSurfaceHolder.addCallback(new MediaSurfaceHolderCallBack()); LinearLayout.LayoutParams para = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT); /* LinearLayout.LayoutParams para = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT); */ //this.setContentView(mediaPlayView); // remove old views this.addContentView(mediaPlayView,para); // keep old views ViewGroup vg = (ViewGroup)mediaPlayView.getParent(); Log.d(TAG,"child count=" + vg.getChildCount()); /* int count = vg.getChildCount(); for(int i=0; i<count; i++){ View view = vg.getChildAt(i); Log.d(TAG,"index=" + i +":view = " + view); }*/ View view0 = vg.getChildAt(0); if(null != view0) view0.bringToFront(); //For supports translucency //1.change "attribs" in cocos\2d\platform\android\nativeactivity.cpp /*const EGLint attribs[] = { EGL_SURFACE_TYPE,EGL_WINDOW_BIT,EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,//EGL_BLUE_SIZE,5,-->delete //EGL_GREEN_SIZE,6,-->delete //EGL_RED_SIZE,-->delete EGL_BUFFER_SIZE,32,//-->new field EGL_DEPTH_SIZE,16,EGL_STENCIL_SIZE,8,EGL_NONE };*/ //2.Set the format of window getWindow().setFormat(PixelFormat.TRANSLUCENT); } MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { Log.d(TAG,"onPrepared..."); int mVideoWidth = 0; int mVideoHeight = 0; mVideoWidth = mp.getVideoWidth(); mVideoHeight = mp.getVideoHeight(); mediaSurfaceHolder.setFixedSize(mVideoWidth,mVideoHeight); mp.start(); //Log.d(TAG,"isPlaying: " + mediaPlayer.isPlaying()); //mediaPlayer.setLooping(true); isMediaPlay = true; } }; private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { Log.d(TAG,"onCompletion..."); //isMediaPlay = false; mp.seekTo(0); mp.start(); } }; @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); } private class MediaSurfaceHolderCallBack implements SurfaceHolder.Callback{ @Override public void surfaceChanged(SurfaceHolder holder,int format,int width,int height) { Log.d(TAG,"surfaceChanged...,width="+width+",height="+height); } @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG,"surfaceCreated..."); mediaPlayer = new MediaPlayer(); mediaPlayer.setOnPreparedListener(mPreparedListener); mediaPlayer.setOnCompletionListener(mCompletionListener); try { //mediaPlayer.setDataSource("/sdcard/video/aoa.mp4"); mediaPlayer.setDataSource("/sdcard/NativeMedia.ts"); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } mediaPlayer.setDisplay(mediaSurfaceHolder); try { mediaPlayer.prepareAsync(); } catch (IllegalStateException e) { e.printStackTrace(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if( mediaPlayer.isPlaying() ){ mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } if( mediaSurfaceHolder != null ){ mediaSurfaceHolder = null; } } } }
1.2 项目中的nativeactivity.cpp
1.2.1 修改EGL属性
其代码变化如下engine_init_display:
#if 0 const EGLint attribs[] = { EGL_SURFACE_TYPE,EGL_BLUE_SIZE,EGL_GREEN_SIZE,EGL_RED_SIZE,EGL_DEPTH_SIZE,EGL_NONE }; #else const EGLint attribs[] = { EGL_SURFACE_TYPE,-->delete //EGL_GREEN_SIZE,-->delete //EGL_RED_SIZE,-->delete EGL_BUFFER_SIZE,//-->new field EGL_DEPTH_SIZE,EGL_NONE }; #endif
1.2.2 清除color buffer
在engine_draw_frame中增加一行代码:glClearColor(0.0f,0.0f,0.0f);
static void engine_draw_frame(struct engine* engine) { LOG_RENDER_DEBUG("engine_draw_frame(...)"); pthread_t thisthread = pthread_self(); LOG_RENDER_DEBUG("pthread_self() = %X",thisthread); // add code to clear color buffer for transparency glClearColor(0.0f,0.0f); if (engine->display == NULL) { // No display. LOGW("engine_draw_frame : No display."); return; } dispatch_pending_runnables(); cocos2d::Director::getInstance()->mainLoop(); LOG_RENDER_DEBUG("engine_draw_frame : just called cocos' mainLoop()"); /* // Just fill the screen with a color. */ /* glClearColor(((float)engine->state.x)/engine->width,engine->state.angle,*/ /* ((float)engine->state.y)/engine->height,1); */ /* glClear(GL_COLOR_BUFFER_BIT); */ if (s_pfEditTextCallback && editBoxText) { s_pfEditTextCallback(editBoxText,s_ctx); free(editBoxText); editBoxText = NULL; } eglSwapBuffers(engine->display,engine->surface); }