cocso引擎整体流程

  任何程序都有入口,mian.cpp; Cocos2d也不免俗,在win32平台下,有一个mian.cpp 入口,从这里进入cocos的世界。

#ifndef __MAIN_H__
#define __MAIN_H__

//WIN32_LEAN_AND_MEAN 是WINDOWS API用于屏蔽一些不常用的API(优化应用程序)才用的。
#define WIN32_LEAN_AND_MEAN             // 从Windows头文件中排除不常用的内容

// Windows 头文件:
#include <windows.h>
#include <tchar.h>

// C 运行时的头文件:
#include "platform/CCStdC.h"

#endif    // __MAIN_H__
main.h
#include "main.h"
#include "../Classes/AppDelegate.h"

USING_NS_CC;

int WINAPI _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,          
                       int       nCmdShow)
{
//以上参数为windows的Api 日后再说
//我们从 UNREFERENCED_PARAMETER 开始吧。这个宏在 winnt.h 中定义如下:
//#define UNREFERENCED_PARAMETER(P) (P)
//换句话说 UNREFERENCED_PARAMETER 展开传递的参数或表达式,其目的是避免编译器关于未引用参数的警告
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    //创建新的App实例
    AppDelegate app;
    //getInstance 单实例模式 获取其实例 运行 由此进入 AppDelegate类
    return Application::getInstance()->run();
}

  在main.cpp中我们可以看到仅仅声明了AppDelegate.h,却使用了run()方法,于是进入AppDelegate.h类中:

class  AppDelegate : private cocos2d::Application

发现其继承于Application,全局搜索Application,在libcocos2d/win32/CCApplication-win32.h 找到了它,查看它的头文件:

class CC_DLL Application : public ApplicationProtocol

发现继承于ApplicationProtocol,再次进入ApplicationProtocol类中查看,

#ifndef __CC_APPLICATION_PROTOCOL_H__
#define __CC_APPLICATION_PROTOCOL_H__

#include "platform/CCPlatformMacros.h"
#include "base/CCAutoreleasePool.h"
#include "base/ccTypes.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,     /**< Windows */
        OS_LINUX,       /**< Linux */
        OS_MAC,         /**< Mac OS X*/
        OS_ANDROID,     /**< Android */
        OS_IPHONE,      /**< iPhone */
        OS_IPAD,        /**< iPad */
        OS_BLACKBERRY,  /**< BlackBerry */
        OS_NACL,        /**< Native Client in Chrome */
        OS_EMSCRIPTEN,  /**< Emscripten */
        OS_TIZEN,       /**< Tizen */
        OS_WINRT,       /**< Windows Runtime Applications */
        OS_WP8          /**< Windows Phone 8 Applications */
    };

    /**
     * @js NA
     * @lua NA
     */
    virtual ~ApplicationProtocol(){
        /** 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
    */
    virtual void applicationDidEnterBackground() = 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(float interval) = 0;
    virtual void setAnimationInterval(float interval, SetIntervalReason reason) = 0;

    /** Subclass override the function to set OpenGL context attribution instead of use default value.
    * And now can only set six attributions:redBits,greenBits,blueBits,alphaBits,depthBits,stencilBits.
    * Default value are(5,6,5,0,16,0), usually use as follows:
    * void AppDelegate::initGLContextAttrs(){
    *     GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};
    *     GLView::setGLContextAttrs(glContextAttrs);
    * }
    */
    virtual void initGLContextAttrs() {}

    /**
    @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;
    
    /**
     @brief Get application version.
     * @js NA
     * @lua NA
     */
    virtual std::string getVersion() = 0;
    
    /**
     @brief Open url in default browser.
     @param String with url to open.
     @return True if the resource located by the URL was successfully opened; otherwise false.
     * @js NA
     * @lua NA
     */
    virtual bool openURL(const std::string &url) = 0;
};

// end of platform group
/** @} */

NS_CC_END

#endif    // __CC_APPLICATION_PROTOCOL_H__

   在这个类中,首先是定义了各个平台的枚举变量,其他的都是虚函数,在不同平台下,不同的类继承这些接口实现跨平台,来到了父类,接下来去实现这些虚方法的win32子类去看一下,在头文件中看它的一些方法声明:

#ifndef __CC_APPLICATION_WIN32_H__
#define __CC_APPLICATION_WIN32_H__

#include "platform/CCPlatformConfig.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32

#include "platform/CCStdC.h"
#include "platform/CCCommon.h"
#include "platform/CCApplicationProtocol.h"
#include <string>

NS_CC_BEGIN

class 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获取当前的应用程序实例。
    @return当前应用程序实例指针。
    */
    static Application* getInstance();

    /** @deprecated Use getInstance() instead */
    CC_DEPRECATED_ATTRIBUTE static Application* sharedApplication();
    
    /* override functions */
    virtual void setAnimationInterval(float interval) override;
    virtual void setAnimationInterval(float interval, SetIntervalReason reason) override;

    virtual LanguageType getCurrentLanguage();

    virtual const char * getCurrentLanguageCode();
    
    /**
     @brief Get target platform
     */
    virtual Platform getTargetPlatform();
    
    /**
    @brief Get application version
    */
    virtual std::string getVersion() override;

    /**
    @brief在默认浏览器中打开网址
    @param打开url的字符串。
    如果成功打开了URL所在的资源,则@return为true;否则是假的。
     */
    virtual bool openURL(const std::string &url);

    /**
    *设置资源根路径。
    * @deprecated请改用FileUtils :: getInstance() - > setSearchPaths()。
     */
    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__

  从上往下看,第一个函数是:

    int run();

它的注释仅仅是:运行消息循环。  进入这个函数发现它做的事情不简单,代码如下:

    UINT TARGET_RESOLUTION = 1; //     1毫秒的目标分辨率
    TIMECAPS tc;
    UINT wTimerRes = 0;
    if (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(TIMECAPS)))
    {
        wTimerRes = std::min(std::max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
        timeBeginPeriod(wTimerRes);
    }

经过查阅资料,弄明白这段首先是更改了window下的计时器的精度,调整为1毫秒;

initGLContextAttrs();

初始化OpenGL属性;

    if (!applicationDidFinishLaunching())
    {
        return 1;
    }

初始化cocos实例,成功继续,不成功返回1;

    while(!glview->windowShouldClose())
    {
        QueryPerformanceCounter(&nNow);
        interval = nNow.QuadPart - nLast.QuadPart;
        if (interval >= _animationInterval.QuadPart)
        {
            nLast.QuadPart = nNow.QuadPart;
            director->mainLoop();
            glview->pollEvents();
        }
        else
        {
            waitMS = (_animationInterval.QuadPart - interval) * 1000LL / freq.QuadPart - 1L;
            if (waitMS > 1L)
                Sleep(waitMS);
        }
    }

这一段所做的事情,就是一个死循环,不停的调用  director->mainLoop();  glview->pollEvents(); 看了注释,和之后的代码,就是不停的刷新,并且在win平台上加了个保护,因为win平台的调度器精度缺失,放在下一帧给cpu处理;

    if (glview->isOpenGLReady())
    {
        director->end();
        director->mainLoop();
        director = nullptr;
    }
    glview->release();
    if (wTimerRes != 0)
    {
        timeEndPeriod(wTimerRes);
    }

这两个就是关闭显示和主循环,win调度器。

  看完run()函数,接下来一看就是个单实例模式:

    static Application* getInstance();

在实现中也是获取Application的唯一实例;

    virtual void setAnimationInterval(float interval) override;
    virtual void setAnimationInterval(float interval, SetIntervalReason reason) override;

这两个是FPS的函数;紧接着几个获取当前语言类型,平台类型,当前版本,打开网址链接的函数

    CC_DEPRECATED_ATTRIBUTE void setResourceRootPath(const std::string& rootResDir);

设置根资源路径,我们在代码中使用FileUtils :: getInstance()->setSearchPaths()代替,就是搜索你的代码和资源的路径;

    CC_DEPRECATED_ATTRIBUTE const std::string& getResourceRootPath(void);

获取路径;

    void setStartupScriptFilename(const std::string& startupScriptFile);

设置开始脚本名字,这个由于没有使用脚本文件,没有仔细去看;

  整个循环到这里也差不多了,进入后台,和进入前台代码并没有分析,在上一节的目录结构就能发现,每一个平台都有一个自己对应的工程,现在发现了一个ApplicationProtocol的父类,每个平台有自己不同的Application来实现对应的方法驱动整个程序,在其中调用run()方法实现启动,在这个引擎中最重要的 Director  Layer  Scene  Sprite 这几个类,他们之间存在这层级关系,之后可以一级一级的去看。

原文地址:https://www.cnblogs.com/zhangthree/p/10494382.html