HelloCpp程序分析

自上一篇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,就显示了我们之前设定的布景。嘿嘿到此结束了,完美顺畅的代码执行流程。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值