cocos2d-x入口类
阅读原文时间:2021年04月21日阅读:1

上一篇文章中有一个在栈中创建的实例——AppDelegate。这个类的初始化使cocos2d-x的程序能够执行起来。由于它是继承于CCApplication类。而执行的run方法就是在此类中实现的。

class CC_DLL CCApplication : public CCApplicationProtocol
{
public:
CCApplication();
virtual ~CCApplication();

/\*\*  
@brief    Run the message loop.  
\*/  
virtual int run();

/\*\*  
@brief    Get current applicaiton instance.  
@return Current application instance pointer.  
\*/  
static CCApplication\* sharedApplication();

/\* override functions \*/  
virtual void setAnimationInterval(double interval);  
virtual ccLanguageType getCurrentLanguage();

/\*\*  
 @brief Get target platform  
 \*/  
virtual TargetPlatform getTargetPlatform();

/\*\*  
 \*  Sets the Resource root path.  
 \*  @deprecated Please use CCFileUtils::sharedFileUtils()->setSearchPaths() instead.  
 \*/  
CC\_DEPRECATED\_ATTRIBUTE void setResourceRootPath(const std::string& rootResDir);

/\*\*  
 \*  Gets the Resource root path.  
 \*  @deprecated Please use CCFileUtils::sharedFileUtils()->getSearchPaths() instead.  
 \*/  
CC\_DEPRECATED\_ATTRIBUTE const std::string& getResourceRootPath(void);

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

const std::string& getStartupScriptFilename(void)  
{  
    return m\_startupScriptFilename;  
}

protected:
HINSTANCE m_hInstance;
HACCEL m_hAccelTable;
LARGE_INTEGER m_nAnimationInterval;
std::string m_resourceRootPath;
std::string m_startupScriptFilename;

static CCApplication \* sm\_pSharedApplication;  

};

NS_CC_END

#endif // __CC_APPLICATION_WIN32_H__

能够看到,CCApplication是继承自于CCApplicationProtocol,CCApplicationProtocol是个纯虚类。生命了程序启动,切到后台,后台唤醒等函数。

class CC_DLL CCApplicationProtocol
{
public:

virtual ~CCApplicationProtocol() {}

/\*\*  
@brief    Implement CCDirector and CCScene init code here.  
@return true    Initialize success, app continue.  
@return false   Initialize failed, app terminate.  
\*/  
//游戏第一次执行时被调用,用于初始场景和载入场景  
virtual bool applicationDidFinishLaunching() = 0;

/\*\*  
@brief  The function be called when the application enter background  
@param  the pointer of the application  
\*/  
//当游戏进入后台时被调用。

virtual void applicationDidEnterBackground() = 0;

/\*\*  
@brief  The function be called when the application enter foreground  
@param  the pointer of the application  
\*/  
//从后台被唤醒时调用。  
virtual void applicationWillEnterForeground() = 0;

/\*\*  
@brief    Callback by CCDirector for limit FPS.  
@interval       The time, expressed in seconds, between current frame and next.  
\*/  
//设置帧数  
virtual void setAnimationInterval(double interval) = 0;

/\*\*  
@brief Get current language config  
@return Current language config  
\*/  
//获取语言  
virtual ccLanguageType getCurrentLanguage() = 0;

/\*\*  
 @brief Get target platform  
 \*/  
//获取执行的平台  
virtual TargetPlatform getTargetPlatform() = 0;  

};

而CCApplication仅仅实现了setAnimationInterval,getCurrentLanguage和getTargetPlatform三个函数,另外三个交给CCApplication的子类,也就是AppDelegate来实现。例如以下代码所看到的:

class AppDelegate : private cocos2d::CCApplication
{
public:
AppDelegate();
virtual ~AppDelegate();

/\*\*  
@brief    Implement CCDirector and CCScene init code here.  
@return true    Initialize success, app continue.  
@return false   Initialize failed, app terminate.  
\*/  
virtual bool applicationDidFinishLaunching();

/\*\*  
@brief  The function be called when the application enter background  
@param  the pointer of the application  
\*/  
virtual void applicationDidEnterBackground();

/\*\*  
@brief  The function be called when the application enter foreground  
@param  the pointer of the application  
\*/  
virtual void applicationWillEnterForeground();  

};

bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
CCDirector* pDirector = CCDirector::sharedDirector();
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();

pDirector->setOpenGLView(pEGLView);

// 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;  

}

// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
CCDirector::sharedDirector()->stopAnimation();

// if you use SimpleAudioEngine, it must be pause  
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();  

}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
CCDirector::sharedDirector()->startAnimation();

// if you use SimpleAudioEngine, it must resume here  
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();  

}

事实上现非常easy。

在applicationDidFinishLaunching函数中先初始化导演。设置是否显示FPS,设置帧率,创建场景。载入和执行场景。applicationDidEnterBackground则让导演停止渲染,applicationWillEnterForeground则让导演继续渲染。

上面说到applicationDidFinishLaunching在程序一启动就会被调用,而在main函数中仅仅是创建了一个AppDelegate的实例。而AppDelegate的实例并没有主动调用该方法,那么它的调用肯定是在它的父类在调用run函数时启动。

int CCApplication::run()
{
PVRFrameEnableControlWindow(false);

// Main message loop:  
MSG msg;  
LARGE\_INTEGER nFreq;  
LARGE\_INTEGER nLast;  
LARGE\_INTEGER nNow;

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

// Initialize instance and cocos2d.  
if (!applicationDidFinishLaunching())  
{  
    return 0;  
}

CCEGLView\* pMainWnd = CCEGLView::sharedOpenGLView();  
pMainWnd->centerWindow();  
ShowWindow(pMainWnd->getHWnd(), SW\_SHOW);

while (1)  
{  
    if (! PeekMessage(&msg, NULL, 0, 0, PM\_REMOVE))  
    {  
        // Get current time tick.  
        QueryPerformanceCounter(&nNow);

        // If it's the time to draw next frame, draw it, else sleep a while.  
        if (nNow.QuadPart - nLast.QuadPart > m\_nAnimationInterval.QuadPart)  
        {  
            nLast.QuadPart = nNow.QuadPart;  
            CCDirector::sharedDirector()->mainLoop();  
        }  
        else  
        {  
            Sleep(0);  
        }  
        continue;  
    }

    if (WM\_QUIT == msg.message)  
    {  
        // Quit message loop.  
        break;  
    }

    // Deal with windows message.  
    if (! m\_hAccelTable || ! TranslateAccelerator(msg.hwnd, m\_hAccelTable, &msg))  
    {  
        TranslateMessage(&msg);  
        DispatchMessage(&msg);  
    }  
}

return (int) msg.wParam;  

}

这个函数的主要逻辑是先调用子类的applicationDidFinishLaunching函数,运行创建场景等操作,然后设置窗体,最后将整个拥有权交给导演类的主循环,也就是死循环中的mainLoop函数的调用,当然在调用前还要推断当前的帧率与上一帧的帧率之差是否大于设置的帧率。否则不调用。

总结:从上面的过程能够看出CCApplication类是整个程序的起始控制类,里面运行了让游戏真正跑起来的主循环,其次还定义了整个程序的运行环境。像设置帧率。获取当前的运行平台等。另外,因为CCApplication是个单例共享类,能够在程序中随时获取当前的平台信息,设置/获取资源的根路径等操作。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器