Cocos2dx Android工程的啟動過程


1、安卓工程下的設置啟動activity為src下面的AppActivity,啟動調用的onCreate並沒有做過多的事情,只是調用了父類Cocos2dxActivity的onCreate。AppActivity代碼如下:

import org.cocos2dx.lib.Cocos2dxActivity;

public class AppActivity extends Cocos2dxActivity {
	@Override
	protected void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		......
    }
}

2、Cocos2dxActivity在cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java里,查看onCreate,代碼如下:

@Override
	protected void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		initFMOD(); //加載聲音庫
		try {
			Class.forName("android.os.AsyncTask");
		} catch (Throwable ignor) {
			ignor.printStackTrace();
		}
		sContext = this;
		PSNetwork.init(sContext); //初始化安卓網絡連接服務
		if (Build.VERSION.SDK_INT >= 23) {
			requestUserPermissions(); //系統的部分授權
		}
		mMacAddress = MacAddressUtil.getMacAddress(sContext);//獲取wifi的MAC地址
		CocosPlayClient.init(this, false); //暫時無用
		boolean isLoadOK = onLoadNativeLibraries(); //把工程中libs下面的so文件load進來,定義在AndroidManifest, meta-data標簽下,android.app.lib_name. 最終在包的data/data/com.XXX.XXX/lib下面
		if (false == isLoadOK) {
			return;
		}

		this.mHandler = new Cocos2dxHandler(this);//處理安卓的彈窗等

		Cocos2dxHelper.init(this);

		this.mGLContextAttrs = getGLContextAttrs();//獲取OpenGLEs的相關屬性
		this.init(); //說明如下文

		if (mVideoHelper == null) {
			mVideoHelper = new Cocos2dxVideoHelper(this, mFrameLayout);
		}

		if (mWebViewHelper == null) {
			mWebViewHelper = new Cocos2dxWebViewHelper(mFrameLayout);
		}

        if(mEditBoxHelper == null){
            mEditBoxHelper = new Cocos2dxEditBoxHelper(mFrameLayout);
        }
		if (null == mScreenListener) {
			mScreenListener = new ScreenListener(this);
			mScreenListener.begin(this);
		}
	}

3、Cocos2dxActivity的init函數如下:

	public void init() {
		// FrameLayout
		ViewGroup.LayoutParams framelayout_params = new ViewGroup.LayoutParams(
				ViewGroup.LayoutParams.MATCH_PARENT,
				ViewGroup.LayoutParams.MATCH_PARENT);
		mFrameLayout = new ResizeLayout(this); //繼承自FrameLayout,看成是一塊畫布(canvas),其他控件添加在上面
		mFrameLayout.setLayoutParams(framelayout_params);

		// Cocos2dxEditText layout
		ViewGroup.LayoutParams edittext_layout_params = new ViewGroup.LayoutParams(
				ViewGroup.LayoutParams.MATCH_PARENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		Cocos2dxEditBox edittext = new Cocos2dxEditBox(this);
		edittext.setLayoutParams(edittext_layout_params);//輸入框

		// ...add to FrameLayout
		mFrameLayout.addView(edittext);

		// Cocos2dxGLSurfaceView
		this.mGLSurfaceView = this.onCreateView();//創建游戲的渲染,接受輸入事件的OpenGL類

		// ...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);

		this.mGLSurfaceView.setCocos2dxRenderer(new Cocos2dxRenderer());//注冊自主實現的渲染器,內容如下
		this.mGLSurfaceView.setCocos2dxEditText(edittext);//輸入框

		this.onCreateFrameLayout();
		// Set framelayout as the content view
		setContentView(mFrameLayout);//設置這個Activity的顯示界面
	}


4、Cocos2dxRenderer,cocos2dx的渲染器,繼承自android.opengl.GLSurfaceView.Renderer,當3中的GLSurfaceView被創建的時候會調用render的onSurfaceCreated()方法; 當GLSurfaceView大小或者橫豎屏發生變化的時候調用render的onSurfaceChanged()方法; 當系統每一次重新畫GLSurfaceView的時候,調用onDrawFrame()方法。所以Cocos2dxRender對這三個方法進行了重寫。

	@Override
	public void onSurfaceCreated(final GL10 GL10, final EGLConfig EGLConfig) {
		Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight);//此處調用了一個定義為native的函數,設置glview等,通過jni來訪問c++實現的方法,接口實現在cocos/platform/android/javaactivity-android.cpp里面,下面的5會繼續講
		this.mLastTickInNanoSeconds = System.nanoTime();
		mNativeInitCompleted = true;
		try{
			Cocos2dxActivity activity = (Cocos2dxActivity) Cocos2dxActivity.getContext();
			activity.onSurfaceCreated(this, GL10, EGLConfig);
		}catch( Throwable e ){
			e.printStackTrace();
		}
	}

@Override
	public void onDrawFrame(final GL10 gl) { //系統自動每秒鍾調用60次這個函數
		/*
		 * No need to use algorithm in default(60 FPS) situation, since
		 * onDrawFrame() was called by system 60 times per second by default.
		 */
		if( true == mIsPaused ){
			return;
		}
		if( mDelayResumeCount <= DELAY_RESUME_COUNT ){
			mDelayResumeCount = mDelayResumeCount + 1;
			if( mDelayResumeCount == DELAY_RESUME_COUNT ){
				Cocos2dxRenderer.nativeOnResume();
				try{
					Cocos2dxActivity activity = (Cocos2dxActivity) Cocos2dxActivity.getContext();
					activity.nativeResume();
				}catch( Throwable e ){
					e.printStackTrace();
				}
			}
			return;
		}
		if (sAnimationInterval <= 1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND) {
			Cocos2dxRenderer.nativeRender(); //大於等於每秒60幀則不經過算法處理,直接執行nativeRender,將在6中有說明
		} else {
			final long now = System.nanoTime();
			final long interval = now - this.mLastTickInNanoSeconds;

			if (interval < Cocos2dxRenderer.sAnimationInterval) { //按照設置的幀數,如果沒有到時間,則sleep到相應的時間
				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();
		}
		try{
			Cocos2dxActivity activity = (Cocos2dxActivity) Cocos2dxActivity.getContext();
			activity.onDrawFrame(this, gl);
		}catch( Throwable e ){
			e.printStackTrace();
		}
	}

	@Override
	public void onSurfaceChanged(final GL10 GL10, final int width,
			final int height) {
		Cocos2dxRenderer.nativeOnSurfaceChanged(width, height);
		try{
			Cocos2dxActivity activity = (Cocos2dxActivity) Cocos2dxActivity.getContext();
			activity.onSurfaceChanged(this, GL10, width, height);
		}catch( Throwable e ){
			e.printStackTrace();
		}
	}

5、 4里面onSurfaceCreated的nativeInit的實現放在cocos/platform/android/javaactivity-android.cpp,方法如下:

void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv*  env, jobject thiz, jint w, jint h)
{
    auto director = cocos2d::Director::getInstance();
    auto glview = director->getOpenGLView();
    if (!glview)
    {
        glview = cocos2d::GLViewImpl::create("Android app");
        glview->setFrameSize(w, h);
        director->setOpenGLView(glview); //設置glview

        //cocos_android_app_init(env, thiz);

        cocos2d::Application::getInstance()->run(); //程序開始運行,android的Application實現放在CCApplication-android.cpp,run的代碼如下
    }
    else
    {
        cocos2d::GL::invalidateStateCache();
        cocos2d::GLProgramCache::getInstance()->reloadDefaultGLPrograms();
        cocos2d::DrawPrimitives::init();
        cocos2d::VolatileTextureMgr::reloadAllTextures();

        cocos2d::EventCustom recreatedEvent(EVENT_RENDERER_RECREATED);
        director->getEventDispatcher()->dispatchEvent(&recreatedEvent);
        director->setGLDefaultValues();
    }
}

int Application::run()
{
    // Initialize instance and cocos2d.
    if (! applicationDidFinishLaunching()) //applicationDidFinishLanunching在自己的Classes/AppDelegate進行重寫,游戲已經啟動
    {
        return 0;
    }
    
    return -1;
}
bool AppDelegate::applicationDidDinishLaunching()
{
	......
	director->setOpenGLView(glview);
	director->setAnimationInterval(1/30.f); //設置幀數,會調用Application-android的setAnimationInterval,再通過JniHelper調用Cocos2dxRenderer中的setAnimationInterval
	director->runWithScene(scene); //
	return true
}

6、關於4中onDrawFrame涉及到的函數nativeRender,它也是一個native類型的函數,實現放在cocos/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp

    JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) {
        cocos2d::Director::getInstance()->mainLoop(); //進入游戲的主循環,Director的mainLoop,事件的分發,渲染,內存池的管理
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM