cocos2d-x3.2——启动过程[Win32]

来源:互联网 发布:手机版导航源码 编辑:程序博客网 时间:2024/04/30 01:18

大部分是转自http://www.cnblogs.com/MianJiang-Developer/p/4039260.html,加上自己的见解和领悟。

1.cocos2d-x是手机游戏跨平台的引擎,首先看一下在win32上的启动流程

进入建立的工程的目录下,包含的文件夹如下图:


Classes文件下是启动类并且与平台无关的文件,以及cocos2dx的类,以及资源文件,剩下的就是各个平台自己的类文件。

2.点击proj.win32进入windows平台下的文件,点击程序入口main.cpp。

main入口[C++程序,为什么是这个入口,计算机的思想与机制]

#include "main.h"#include "AppDelegate.h"USING_NS_CC;int APIENTRY _tWinMain(HINSTANCE hInstance,                       HINSTANCE hPrevInstance,                       LPTSTR    lpCmdLine,                       int       nCmdShow){    UNREFERENCED_PARAMETER(hPrevInstance);    UNREFERENCED_PARAMETER(lpCmdLine);    // create the application instance    AppDelegate app;    return Application::getInstance()->run();}


实例AppDelegate类型的app,并且返回了return Application::getInstance()->run()

3.为什么实例了AppDelegate却没有调用AppDelegate的函数,反而调用了Application类的run()

其实Application是AppDelegate的父类,实例AppDelegate的时候也实例了Application.

注:Application是平台相关的类,实现在win32平台下


贴出Application 类的声明

/****************************************************************************Copyright (c) 2010-2012 cocos2d-x.orgCopyright (c) 2013-2014 Chukong Technologies Inc.http://www.cocos2d-x.orgPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.****************************************************************************/#ifndef __CC_APPLICATION_WIN32_H__#define __CC_APPLICATION_WIN32_H__#include "base/CCPlatformConfig.h"#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32#include "CCStdC.h"#include "platform/CCCommon.h"#include "platform/CCApplicationProtocol.h"#include <string>NS_CC_BEGINclass Rect;class CC_DLL Application : public ApplicationProtocol{public:    /**     * @js ctor     */    Application();    /**     * @js NA     * @lua NA     */    virtual ~Application();    /**    @brief    Run the message loop.    */    int run();    /**    @brief    Get current applicaiton instance.    @return Current application instance pointer.    */    static Application* getInstance();    /** @deprecated Use getInstance() instead */    CC_DEPRECATED_ATTRIBUTE static Application* sharedApplication();        /* override functions */    virtual void setAnimationInterval(double interval);    virtual LanguageType getCurrentLanguage();virtual const char * getCurrentLanguageCode();        /**     @brief Get target platform     */    virtual Platform getTargetPlatform();    /**     *  Sets the Resource root path.     *  @deprecated Please use FileUtils::getInstance()->setSearchPaths() instead.     */    CC_DEPRECATED_ATTRIBUTE void setResourceRootPath(const std::string& rootResDir);    /**      *  Gets the Resource root path.     *  @deprecated Please use FileUtils::getInstance()->getSearchPaths() instead.      */    CC_DEPRECATED_ATTRIBUTE const std::string& getResourceRootPath(void);    void setStartupScriptFilename(const std::string& startupScriptFile);    const std::string& getStartupScriptFilename(void)    {        return _startupScriptFilename;    }protected:    HINSTANCE           _instance;    HACCEL              _accelTable;    LARGE_INTEGER       _animationInterval;    std::string         _resourceRootPath;    std::string         _startupScriptFilename;    static Application * sm_pSharedApplication;};NS_CC_END#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32#endif    // __CC_APPLICATION_WIN32_H__

这个类CCApplication提供了一些设置/获取平台相关的参数和一个关键的run()函数。同时它是一个抽象类,因为塌继承自ApplicationProtocol,

但是并没有实现ApplicationProtocal这个纯虚函数,因此Application并不能直接实例化。

(1)Application维护了一个指向本类型的指针[this的用法在我前面的博客里介绍过]

static Application * sm_pSharedApplication;
在构造函数中指针指向了本身,并且在getInstance()中返回

Application::Application(): _instance(nullptr), _accelTable(nullptr){    _instance    = GetModuleHandle(nullptr);    _animationInterval.QuadPart = 0;    CC_ASSERT(! sm_pSharedApplication);    sm_pSharedApplication = this;}
Application* Application::getInstance(){    CC_ASSERT(sm_pSharedApplication);    return sm_pSharedApplication;}
而 Application 是并不能被实例化的,因此只有当 Application 的子类被构造时,它的构造函数才会被调用,且 getInstance() 返回的也是指向子类的指针。[指向子类的指针,构造子类,返回的是子类的指针?]


这样就解释了开始的疑问, AppDelegate 类是 Application 类的直接子类。所以

Application::getInstance() -> run()
就相当于

app -> run() 

(2)run() 函数探究

int Application::run(){    PVRFrameEnableControlWindow(false);    // Main message loop:    LARGE_INTEGER nFreq;    LARGE_INTEGER nLast;    LARGE_INTEGER nNow;    QueryPerformanceFrequency(&nFreq);    QueryPerformanceCounter(&nLast);    // Initialize instance and cocos2d.    if (!applicationDidFinishLaunching())    {        return 0;    }    auto director = Director::getInstance();    auto glview = director->getOpenGLView();    // Retain glview to avoid glview being released in the while loop    glview->retain();    while(!glview->windowShouldClose())    {        QueryPerformanceCounter(&nNow);        if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)        {            nLast.QuadPart = nNow.QuadPart;                        director->mainLoop();            glview->pollEvents();        }        else        {            Sleep(0);        }    }    // Director should still do a cleanup if the window was closed manually.    if (glview->isOpenGLReady())    {        director->end();        director->mainLoop();        director = nullptr;    }    glview->release();    return true;}
在这个函数中,

 // Main message loop:
    LARGE_INTEGER nFreq;
    LARGE_INTEGER nLast;
    LARGE_INTEGER nNow;


    QueryPerformanceFrequency(&nFreq);
    QueryPerformanceCounter(&nLast);

这段是取得系统高精度计时器次数和频率用来计算每一帧经过的时间(大致是这么个意思,这两个函数的用法可以参考此处)

   // Initialize instance and cocos2d.    if (!applicationDidFinishLaunching())    {        return 0;    }
调用 applicationDidFinishLaunching() 。这个函数我们很熟悉,但是他并没有在Application里被实现,它实际上是Application类的父类ApplicationProtocl声明的接口。真正的实现是在 AppDelegate 类中。因此这里调用的是AppDelegate类的 applicationDidFinishLaunching() 函数。[虚函数的实现原理,我的博客里也有讲过]

(3)再来顺便看看 ApplicationProtocol 类,这也是个抽象类,它定义了一系列平台无关,而与引擎生命周期相关的纯虚函数接口,所有平台的 Application 类型都继承于此。所谓求同存异,大致如此。

ApplicationProtocal的类位置在


声明如下:

/****************************************************************************Copyright (c) 2010-2012 cocos2d-x.orgCopyright (c) 2013-2014 Chukong Technologies Inc.http://www.cocos2d-x.orgPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.****************************************************************************/#ifndef __CC_APPLICATION_PROTOCOL_H__#define __CC_APPLICATION_PROTOCOL_H__#include "base/CCPlatformMacros.h"#include "base/CCScriptSupport.h"#include "base/CCAutoreleasePool.h"NS_CC_BEGIN/** * @addtogroup platform * @{ */class CC_DLL ApplicationProtocol{public:    // Since WINDOWS and ANDROID are defined as macros, we could not just use these keywords in enumeration(Platform).    // Therefore, 'OS_' prefix is added to avoid conflicts with the definitions of system macros.    enum class Platform    {        OS_WINDOWS,        OS_LINUX,        OS_MAC,        OS_ANDROID,        OS_IPHONE,        OS_IPAD,        OS_BLACKBERRY,        OS_NACL,        OS_EMSCRIPTEN,        OS_TIZEN,        OS_WINRT,        OS_WP8    };    /**     * @js NA     * @lua NA     */    virtual ~ApplicationProtocol(){#if CC_ENABLE_SCRIPT_BINDING        ScriptEngineManager::destroyInstance();#endif        // clean auto release pool        PoolManager::destroyInstance();    }    /**    @brief    Implement Director and Scene init code here.    @return true    Initialize success, app continue.    @return false   Initialize failed, app terminate.    * @js NA    * @lua NA    */    virtual bool applicationDidFinishLaunching() = 0;    /**    @brief  This function will be called when the application enters background.    * @js NA    * @lua NA    */    <pre name="code" class="html">virtual bool applicationDidFinishLaunching() = 0;virtual void applicationDidEnterBackground() = 0;virtual void applicationWillEnterForeground() = 0;virtual void setAnimationInterval(double interval)= 0;

/** @brief This function will be called when the application enters foreground. * @js NA * @lua NA */ virtual void applicationWillEnterForeground() = 0; /** @brief Callback by Director for limit FPS. @param interval The time, expressed in seconds, between current frame and next. * @js NA * @lua NA */ virtual void setAnimationInterval(double interval) = 0; /** @brief Get current language config @return Current language config * @js NA * @lua NA */ virtual LanguageType getCurrentLanguage() = 0; /** @brief Get current language iso 639-1 code @return Current language iso 639-1 code * @js NA * @lua NA */ virtual const char * getCurrentLanguageCode() = 0; /** @brief Get target platform * @js NA * @lua NA */ virtual Platform getTargetPlatform() = 0;};// end of platform group/// @}NS_CC_END#endif // __CC_APPLICATION_PROTOCOL_H__


可以看到,
virtual bool applicationDidFinishLaunching() = 0;virtual void applicationDidEnterBackground() = 0;virtual void applicationWillEnterForeground() = 0;

这几个函数都是游戏在不同生命周期下会被调用的,它们都在 AppDelegate 类中实现。

applicationDidFinishLaunching() 实际上只是做了一些初始化,一般我们是定义一个场景,后用director->runWithScene(scene)。 你可以看看runWithScene() 的实现,只是把场景压栈,真正的运行还在后面:

    // Retain glview to avoid glview being released in the while loop    glview->retain();    while(!glview->windowShouldClose())    {        QueryPerformanceCounter(&nNow);        if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)        {            nLast.QuadPart = nNow.QuadPart;                        director->mainLoop();            glview->pollEvents();        }        else        {            Sleep(0);        }    }
在这个循环中,当当前时间与上次记录的时间间隔大于一帧所占用的时间时,说明需要进入下一帧,调用mainLoop(),由此实现每一帧都进入引擎的内部流程。

mainLoop()函数内部实现了很多功能,包括OpenGL的渲染,内存管理,定时器任务执行等。

0 0