cocos2d-x学习日志(18) --程序是怎样開始执行与结束?
问题的由来
怎么样使用 Cocos2d-x 高速开发游戏。方法非常easy,你能够看看其自带的例程,或者从网上搜索教程,执行起第一个HelloWorld,然后在 HelloWorld 里面写相关逻辑代码。加入我们的层、精灵等 ~ 我们并不一定须要知道 Cocos2d-x 是怎样执行或者在各种平台之上执行,也不用知道 Cocos2d-x 的游戏是怎样执行起来的。它又是怎样渲染界面的 ~~~
两个入口
程序入口的概念是相对的,AppDelegate 作为跨平台程序入口,在这之上做了还有一层的封装,封装了不同平台的不同实现。比方我们通常觉得一个程序是由 main 函数開始执行,那我们就去找寻。我们看到了在proj.win32文件夹下存在 main.cpp 文件,这就是我们要看的内容,例如以下:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); #ifdef USE_WIN32_CONSOLE
AllocConsole();
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
#endif // create the application instance
AppDelegate app;
CCEGLView* eglView = CCEGLView::sharedOpenGLView();
eglView->setViewName("HelloLua");
eglView->setFrameSize(480, 320);
int ret = CCApplication::sharedApplication()->run(); #ifdef USE_WIN32_CONSOLE
FreeConsole();
#endif return ret;
}
在这里我们看见了程序的真正入口,包括一个 main 函数。从此进入。执行 cocos2d-x 程序。
Android:
我们找到 Android 平台与上面 等价 的入口点,proj.android\jni\hellolua\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();
}
}
我们并没有看到所谓的 main 函数,这是因为不同的平台封装所以有着不同的实现,在 Android 平台,默认是使用 Java 开发,能够使用 Java 通过 Jni 调用 C++ 程序。而这里也正式如此。
我们暂且仅仅需知道。由 Android 启动一个应用,通过各种峰回路转,终于执行到了Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit 函数。由此,变開始了我们 cocos2d-x Android 平台的程序入口处。对于跨平台的 cocos2d-x 来说,除非必要,否则可不必深究其理,比方想要使用 Android 平台固有的特性等,那就须要很多其它的了解 Jni 用法,以及 Android 操作系统的很多其它细节。
程序的流程 (这里以 Win32的实现为主。其它平台触类旁通就可以)
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmV4dWVmZW5neWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="688" height="358" alt="" />
凝视:
我们从 main.cpp 中 CCApplication::sharedApplication()–>run(); 这一句看起。这一句标志着, cocos2d-x 程序正式開始执行。一点点開始分析,我们定位到 sharedApplication() 方法的实现。
CCApplication.cpp:
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;
} void CCApplication::setAnimationInterval(double interval)
{
LARGE_INTEGER nFreq;
QueryPerformanceFrequency(&nFreq);
m_nAnimationInterval.QuadPart = (LONGLONG)(interval * nFreq.QuadPart);
} //////////////////////////////////////////////////////////////////////////
// static member function
//////////////////////////////////////////////////////////////////////////
CCApplication* CCApplication::sharedApplication()
{
CC_ASSERT(sm_pSharedApplication);
return sm_pSharedApplication;
}
从 sharedApplication() 方法,到 run() 方法。在这之前,我们须要调用到它的构造函数,否则不能执行。这就是为什么在 CCApplication::sharedApplication()–>run();
之前,我们首先使用了 AppDelegate app; 创建 AppDelegate 变量的原因!
AppDelegate 和 CCAppliation 是什么关系!
由 AppDelegate 的定义我们能够知道,它是 CCApplication 的子类,在创建子类对象的时候,调用其构造函数的同一时候。父类构造函数也会执行,然后就将 AppDelegate 的对象赋给了 CCApplication 的静态变量,而在 AppDelegate 之中我们实现了applicationDidFinishLaunching 方法,所以在 CCApplication 中 run 方法的開始处调用的就是 AppDelegate 之中的实现。而我们在此方法中我们初始化了一些变量,创建了第一个 CCScene 场景等。之后的控制权,便全权交给了 CCDirector::sharedDirector()–>mainLoop(); 方法了。
从 CCApplication 到 CCDirector
CCDirector* CCDirector::sharedDirector(void)
{
if (!s_SharedDirector)
{
s_SharedDirector = new CCDisplayLinkDirector();
s_SharedDirector->init();
} return s_SharedDirector;
} void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene(); // release the objects
CCPoolManager::sharedPoolManager()->pop();
}
}
游戏的执行以场景为基础。每时每刻都有一个场景正在执行,其内部有一个场景栈,遵循后进后出的原则,当我们显示的调用 end() 方法,或者弹出当前场景之时,其自己主动推断,假设没有场景存在,也会触发 end() 方法,以说明场景执行的结束,而游戏假设没有场景,就像演出没有了舞台,程序进入最后收尾的工作,通过改动变量 m_bPurgeDirecotorInNextLoop 促使在程序 mainLoop 方法之内调用 purgeDirector方法。
void CCEGLView::end()
{
if (m_hWnd)
{
#if(_MSC_VER >= 1600)
if(m_bSupportTouch)
{
s_pfUnregisterTouchWindowFunction(m_hWnd);
}
#endif /* #if(_MSC_VER >= 1600) */
DestroyWindow(m_hWnd);
m_hWnd = NULL;
}
s_pMainWindow = NULL;
UnregisterClass(kWindowClassName, GetModuleHandle(NULL));
delete this;
}
end() 方法非常easy,仅仅须要看到最后一句 delete this; 就明确了。
最新文章
- 《JAVA与模式》之观察者模式
- Java中的main()方法详解
- @JsonFormat时间不对
- PC-红警联机问题与下载
- Bash中的数组
- python高级编程之超类02:super的缺陷
- Object-c学习之路(oc点语法)
- .net core 时间戳转换
- IE去掉input的type=”text”输入内容时出现的X和type=”password”出现的眼睛图标
- 初识 Javascript.01 -- Javascript基础|输出方式、变量、变量命名规范、数据类型、
- ssm框架之将数据库的数据导入导出为excel文件
- 小米5.0以上系统如何没ROOT激活xposed框架的经验
- Numpy进阶操作
- 树·AVL树/平衡二叉树
- mobile_点透_传透_touch-action
- Eclipse上传项目到Git
- ASP.NET Easyui datagrid增删改+sqlhelper
- django之COOKIE 与 SESSION
- 粗略的整改一下blog
- sharding-jdbc之——分库分表实例