Cocos2d-x程序在Android下的启动过程
public class HelloLua extends Cocos2dxActivity{ protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); } public Cocos2dxGLSurfaceView onCreateGLSurfaceView() { return new LuaGLSurfaceView(this); } static { System.loadLibrary("hellolua"); } }
从上面的代码,启动Activity是继承Cocos2dxActivity的,在游戏启动时,Activity首先会执行静态代码块,加载libhellolua.so库,这个动态链接库是在用NDK编译的时候生成的;然后就是执行onCreate方法,这里调用了父类Cocos2dxActivity的onCreate方法。 Cocos2dxActivity在
$(sourcedir)\cocos2dx\platform\android\java\src\org\cocos2dx\lib\Cocos2dxActivity.java
中定义,其OnCreate方法代码如下:
protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); sContext = this; this.mHandler = new Cocos2dxHandler(this); this.init(); Cocos2dxHelper.init(this, this); }
这里主要是执行初始化过程,Cocos2dxHandler主要处理显示Dialog的消息,Cocos2dxHelper是个辅助类,我们主要看init()方法,代码如下:
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 layout 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); // ...add to FrameLayout framelayout.addView(edittext); // Cocos2dxGLSurfaceView this.mGLSurfaceView = this.onCreateView(); // ...add to FrameLayout framelayout.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); // Set framelayout as the content view setContentView(framelayout); }
public Cocos2dxGLSurfaceView onCreateView() { return new Cocos2dxGLSurfaceView(this); }
$(sourcedir)\cocos2dx\platform\android\java\src\org\cocos2dx\lib\Cocos2dxGLSurfaceView.java
中定义,它继承自opengl中类GLSurfaceView。GLSurfaceView的核心就是Renderer,初始化时会调用Renderer的onSurfaceCreated方法,每一帧的绘制是通过调用Renderer的onDrawFrame方法。Cocos2dxGLSurfaceView的Renderer是一个Cocos2dxRenderer对象,类Cocos2dxRenderer在
$(sourcedir)\cocos2dx\platform\android\java\src\org\cocos2dx\lib\Cocos2dxRenderer.java
中定义,其方法onSurfaceCreated代码如下:
public void onSurfaceCreated(final GL10 pGL10, final EGLConfig pEGLConfig) { Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight); this.mLastTickInNanoSeconds = System.nanoTime(); }
这里主要调用了一个方法nativeInit,nativeInit被声明为:
private static native void nativeInit(final int pWidth, final int pHeight);
即它是一个native的函数,即该函数用C++代码中实现,关于native函数简单说,就是在java在调用C++代码实现的函数,即需要采用JNI技术(可以看成是Java与C++交互的一个协议~)。方法nativeInit对应的C++实现是在(sourcedir)\samples\Lua\HelloLua\proj.android\jni\hellolua\main.cpp中:
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 { ..... } }
CCDirector* CCDirector::sharedDirector(void) { if (!s_SharedDirector) { s_SharedDirector = new CCDisplayLinkDirector(); s_SharedDirector->init(); } return s_SharedDirector; }
这里的CCCCDisplayLinkDirector是CCDirector的子类,方法init()做一些初始化工作:
bool CCDirector::init(void) { setDefaultValues(); //场景相关 ... ... //管理场景的数组栈 m_pobScenesStack = new CCArray(); m_pobScenesStack->init(); // 一些FPS等相关的成员变量初始化 ... ... //初始化调度器对象 m_pScheduler = new CCScheduler(); //动作管理器对象 m_pActionManager = new CCActionManager(); m_pScheduler->scheduleUpdateForTarget(m_pActionManager, kCCPrioritySystem, false); // touchDispatcher,KeypadDispatcher,Accelerometer等对象初始化 ... ... // CCPoolManager中实现了cocos2d-x CCObject对象的内存管理机制 CCPoolManager::sharedPoolManager()->push(); return true; }
创建好导演对象后,Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit中调用了该对象的getOpenGLView方法:
inline CCEGLView* getOpenGLView(void) { return m_pobOpenGLView; }
该方法返回用于游戏绘制的CCEGLView,在init()中,m_pobOpenGLView复制为NULL。在Android平台下,这个CCEGLView其实没有什么作用,因为游戏都是绘制在Cocos2dxGLSurfaceView上的,因此方法Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit接着执行if分支:
CCEGLView *view = CCEGLView::sharedOpenGLView(); view->setFrameSize(w, h);
这里同样创建了游戏中类CCEGLView的唯一实例,类在$(sourcedir)\cocos2dx\platform\android\CCEGLView.cpp中实现。接着执行
AppDelegate *pAppDelegate = new AppDelegate(); CCApplication::sharedApplication()->run();
创建了一个类AppDelegate对象,类AppDelegate在$(sourcedir)\samples\Lua\HelloLua\Classes\AppDelegate.cpp中实现,类AppDelegate在各个平台之间共用的:
class AppDelegate : private cocos2d::CCApplication { public: AppDelegate(); virtual ~AppDelegate(); virtual bool applicationDidFinishLaunching(); virtual void applicationDidEnterBackground(); virtual void applicationWillEnterForeground(); };
该类继承自CCApplication,注意类CCApplication是在$(sourcedir)\cocos2dx\platform\android\CCApplication.cpp中实现的,它的实现是与平台相关的。创建AppDelegate实例的工作实质就是实例化CCApplication,它的构造函数代码如下:
CCApplication::CCApplication() { CCAssert(! sm_pSharedApplication, ""); sm_pSharedApplication = this; }
因此在实例化AppDelegate时,主要工作是用AppDelegate对象初始化全局变量sm_pSharedApplication。接着后面调用CCApplication::sharedApplication()->run(),相关代码如下:
CCApplication* CCApplication::sharedApplication() { CCAssert(sm_pSharedApplication, ""); return sm_pSharedApplication; } int CCApplication::run() { // Initialize instance and cocos2d. if (! applicationDidFinishLaunching()) { return 0; } return -1; }
run中调用的虚函数applicationDidFinishLaunching实质上调用的是子类AppDelegate中的applicationDidFinishLaunching,代码如下:
bool AppDelegate::applicationDidFinishLaunching() { //初始化director CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); CCEGLView::sharedOpenGLView()->setDesignResolutionSize(480, 320, kResolutionNoBorder); //显示FPS pDirector->setDisplayStats(true); // 设置FPS pDirector->setAnimationInterval(1.0 / 60); //创建Lua脚本引擎 CCLuaEngine* pEngine = CCLuaEngine::defaultEngine(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); //加载执行lua脚本 std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename("hello.lua"); pEngine->executeScriptFile(path.c_str()); return true; }
public void onDrawFrame(final GL10 gl) { Cocos2dxRenderer.nativeRender(); }
其唯一的工作是调用了nativeRender方法,该方法是native的,其对应的实现是:
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) { cocos2d::CCDirector::sharedDirector()->mainLoop(); }
即执行导演对象中的方法mainLoop:
void CCDisplayLinkDirector::mainLoop(void) { // 此变量决定程序是否结束 if (m_bPurgeDirecotorInNextLoop) { m_bPurgeDirecotorInNextLoop = false; purgeDirector(); } else if (! m_bInvalid) { //屏幕绘制,并做一些相应的逻辑处理 drawScene(); // 释放对象管理器中CCObject 对象 CCPoolManager::sharedPoolManager()->pop(); } }
这个方法就是所有平台最后真正执行的循环体。
参考资料