展会信息港展会大全

Cocos2d-x程序在Android下的启动过程
来源:互联网   发布日期:2015-09-28 10:38:03   浏览:3330次  

导读: 注:原文也在公司内部论坛上发了 本文通过分析cocos2d-x(分析版本为cocos2d-x-2.2.1)自身提供的示例程序HelloLua(在目录$(sourcedir)samplesLua...

注:原文也在公司内部论坛上发了 本文通过分析cocos2d-x(分析版本为cocos2d-x-2.2.1)自身提供的示例程序HelloLua(在目录$(sourcedir)samplesLuaHelloLua下)来分析cocos2d-x的在android平台下的具体启动过程。 我们知道android平台的游戏是从一个Activity开始的。HelloLua的启动Activity是在文件HelloLua.java中定义的,相关代码如下:

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

}

init()方法就是为Activity绑定View Hierarchy,这里的FrameLayout是根View,FrameLayout又包含一个Cocos2dxEditText和一个Cocos2dxGLSurfaceView,这个Cocos2dxGLSurfaceView的实例在方法onCreateView中创建的,代码非常简单,如下:

public Cocos2dxGLSurfaceView onCreateView() {

return new Cocos2dxGLSurfaceView(this);

}

而类Cocos2dxGLSurfaceView本身是在

$(sourcedir)cocos2dxplatformandroidjavasrcorgcocos2dxlibCocos2dxGLSurfaceView.java

中定义,它继承自opengl中类GLSurfaceView。GLSurfaceView的核心就是Renderer,初始化时会调用Renderer的onSurfaceCreated方法,每一帧的绘制是通过调用Renderer的onDrawFrame方法。Cocos2dxGLSurfaceView的Renderer是一个Cocos2dxRenderer对象,类Cocos2dxRenderer在

$(sourcedir)cocos2dxplatformandroidjavasrcorgcocos2dxlibCocos2dxRenderer.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)samplesLuaHelloLuaproj.androidjnihelloluamain.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

{

.....

}

}

这里的函数命名Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit是完全按照JNI实现方法的命名规则。CCDirector就是是cocos2d-x中的导演类,该类在$(sourcedir)cocos2dxCCDirector.cpp中实现。方法sharedDirector是类CCDirector的一个静态方法,该方法用来创建游戏中唯一的CCDirector对象,代码如下:

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)cocos2dxplatformandroidCCEGLView.cpp中实现。接着执行

AppDelegate *pAppDelegate = new AppDelegate();

CCApplication::sharedApplication()->run();

创建了一个类AppDelegate对象,类AppDelegate在$(sourcedir)samplesLuaHelloLuaClassesAppDelegate.cpp中实现,类AppDelegate在各个平台之间共用的:

classAppDelegate : private cocos2d::CCApplication

{

public:

AppDelegate();

virtual ~AppDelegate();

virtual bool applicationDidFinishLaunching();

virtual void applicationDidEnterBackground();

virtual void applicationWillEnterForeground();

};

该类继承自CCApplication,注意类CCApplication是在$(sourcedir)cocos2dxplatformandroidCCApplication.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;

}

至此游戏启动完成,但是我们并没看到类似while循环的东东(btw,分析windows和Linux平台上cocos2d-x的启动流程可以清楚看到类似while循环东东~),这是因为在android平台下,主循环是由渲染线程发起的,通过不断调用render来驱动的,具体说就是调用Java类Cocos2dxRenderer中的onDrawFrame方法:

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();

}

}

这个方法就是所有平台最后真正执行的循环体。

赞助本站

人工智能实验室
AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港