HelloCpp程序分析

来源:互联网 发布:苹果机下载不了软件 编辑:程序博客网 时间:2024/05/22 14:54

自上一篇HelloCpp之后,demo(别人的Demo)是完成了,但是只是知其然而不是知其所以然,自己想要独立去完成还是欠缺很多的,所以结合网上的笔记摘抄一下该程序的入口如下:

    package org.cocos2dx.hellocpp;      import org.cocos2dx.lib.Cocos2dxActivity;      import android.os.Bundle;      public class HelloCpp extends Cocos2dxActivity{          protected void onCreate(Bundle savedInstanceState){              super.onCreate(savedInstanceState);          }          static {               System.loadLibrary("hellocpp");          }      }  
HelloCpp首先执行静态代码块,也即执行加载动态库,(个人理解,应该首先编译完成,我们书写的代码成为可执行代码,再进行onCreate等代码,再执行动态库里的内容,对吧?),加载完成后执行onCreate函数,而该函数执行的又是父类的onCreate也即Cocos2dxActivity的onCreate,代码如下:

protected void onCreate(final Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          sContext = this;          this.mHandler = new Cocos2dxHandler(this);          this.init();          Cocos2dxHelper.init(this, this);      }  

cocos2dxHelper是一个辅助类,我们主要看一下cocos2dxActivity的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);          }  
这里就是为Activity绑定View Hierarchy,大家做Android开发的对着一定很熟悉。View Hierarchy的根View是个FrameLayout,FrameLayout又包含一个EditText和一个GLSurfaceView,这个GLSurfaceView就是cocos引擎用来绘制游戏画面的关键View,我们来详细分析一下它。首先看一下Cocos2dxActivity的onCreateView方法:

    public Cocos2dxGLSurfaceView onCreateView() {              return new Cocos2dxGLSurfaceView(this);          }  

该方法就是新建一个Cocos2dxGLSurfaceView,Cocos2dxGLSurfaceView又继承于GLSurfaceView。我们都知道GLSurfaceView的核心就是Renderer,初始化时会调用Renderer的onSurfaceCreated方法,每一帧的绘制是通过调用Renderer的onDrawFrame方法。Cocos2dxGLSurfaceView的Renderer是一个Cocos2dxRenderer对象,我们先来看Cocos2dxRenderer对象的onSurfaceCreated方法:
public void onSurfaceCreated(final GL10 pGL10, final EGLConfig pEGLConfig) {          Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight);          this.mLastTickInNanoSeconds = System.nanoTime();      }  
这里调用了一个本地方法nativeInit(final int pWidth, final int pHeight),本地方法的实现在jni/hellocpp/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    {        ccGLInvalidateStateCache();        CCShaderCache::sharedShaderCache()->reloadDefaultShaders();        ccDrawInit();        CCTextureCache::reloadAllTextures();        CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_FOREGROUND, NULL);        CCDirector::sharedDirector()->setGLDefaultValues();     }}

CCDirector是游戏的导演类,一个游戏只有一个导演类用来控制和管理场景。CCDirector::sharedDirector()是个静态方法,用来获取导演类的单例对象.

该方法返回用于游戏绘制的CCEGLView,在Android平台下,这个CCEGLView其实没有什么作用,因为游戏都是绘制在Cocos2dxGLSurfaceView上的。由于我们是初始化过程,所以此时m_pobOpenGLView为null,所以if (!CCDirector::sharedDirector()->getOpenGLView())条件成立,执行以下的代码:

CCEGLView *view = CCEGLView::sharedOpenGLView();view->setFrameSize(w, h);AppDelegate *pAppDelegate = new AppDelegate();CCApplication::sharedApplication()->run();
而AppDelegate就是委托代理类,该类代理导演类执行所有操作

  AppDelegate *pAppDelegate = new AppDelegate();
该代码的执行完成了一项操作,而该项操作则是将新建的AppDelegate指针赋给了全局变量sm_pSharedApplication = this
进而执行的CCApplication::ShareAppcation()->run();,而CCApplication::ShareAppcation()的返回值就是sm_pSharedApplication,也即将要执行的是CCApplication的run函数

    int CCApplication::run()      {          // Initialize instance and cocos2d.          if (! applicationDidFinishLaunching())          {              return 0;          }          return -1;      }  
接下来要做的操作就是applicationDidFinishLaunching函数,而该函数则是定义在AppDelegate.cpp中的

bool AppDelegate::applicationDidFinishLaunching() {    // initialize director    CCDirector* pDirector = CCDirector::sharedDirector();    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();    pDirector->setOpenGLView(pEGLView);CCSize frameSize = pEGLView->getFrameSize();    // Set the design resolution#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)    pEGLView->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, kResolutionShowAll);#else    pEGLView->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, kResolutionNoBorder);#endif        vector<string> searchPath;    // In this demo, we select resource according to the frame's height.    // If the resource size is different from design resolution size, you need to set contentScaleFactor.    // We use the ratio of resource's height to the height of design resolution,    // this can make sure that the resource's height could fit for the height of design resolution.    // if the frame's height is larger than the height of medium resource size, select large resource.if (frameSize.height > mediumResource.size.height){        searchPath.push_back(largeResource.directory);        pDirector->setContentScaleFactor(MIN(largeResource.size.height/designResolutionSize.height, largeResource.size.width/designResolutionSize.width));}    // if the frame's height is larger than the height of small resource size, select medium resource.    else if (frameSize.height > smallResource.size.height)    {        searchPath.push_back(mediumResource.directory);                pDirector->setContentScaleFactor(MIN(mediumResource.size.height/designResolutionSize.height, mediumResource.size.width/designResolutionSize.width));    }    // if the frame's height is smaller than the height of medium resource size, select small resource.else    {        searchPath.push_back(smallResource.directory);        pDirector->setContentScaleFactor(MIN(smallResource.size.height/designResolutionSize.height, smallResource.size.width/designResolutionSize.width));    }    // set searching path    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPath);    // turn on display FPS    pDirector->setDisplayStats(true);    // set FPS. the default value is 1.0/60 if you don't call this    pDirector->setAnimationInterval(1.0 / 60);    // create a scene. it's an autorelease object    CCScene *pScene = HelloWorld::scene();    // run    pDirector->runWithScene(pScene);    return true;}
所有操作完成后,我们只需要看一下接下来要做的事情,涉及到了runWithScene,查看HelloWorldScene.cpp我们可以看到init函数才是我们自己定义的布景函数,但是我们自己并未手动调用,对吧?现在看一下scene函数

CCScene* HelloWorld::scene(){    // 'scene' is an autorelease object    CCScene *scene = CCScene::create();        // 'layer' is an autorelease object    HelloWorld *layer = HelloWorld::create();    // add layer as a child to scene    scene->addChild(layer);    // return the scene    return scene;}

而其中的create函数则是HelloWorldScene中有一个CREATE_FUNC(HelloWorld);的定义

#define CREATE_FUNC(__TYPE__) \static __TYPE__* create() \{ \    __TYPE__ *pRet = new __TYPE__(); \    if (pRet && pRet->init()) \    { \        pRet->autorelease(); \        return pRet; \    } \    else \    { \        delete pRet; \        pRet = NULL; \        return NULL; \    } \}
也即内部调用了init()函数。最后runWithscene,就显示了我们之前设定的布景。嘿嘿到此结束了,完美顺畅的代码执行流程。。。


0 0
原创粉丝点击