问题的由来

怎么样使用 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

      cocos2d-x 程序已经执行起来了。我们继续下一步,mainLoop 函数:
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方法。

      走到最后一步,看 CCEGLView 是假设负责收尾工作的:
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; 就明确了。

參考博文:http://blog.leafsoar.com/archives/2013/05-05.html

最新文章

  1. 《JAVA与模式》之观察者模式
  2. Java中的main()方法详解
  3. @JsonFormat时间不对
  4. PC-红警联机问题与下载
  5. Bash中的数组
  6. python高级编程之超类02:super的缺陷
  7. Object-c学习之路(oc点语法)
  8. .net core 时间戳转换
  9. IE去掉input的type=”text”输入内容时出现的X和type=”password”出现的眼睛图标
  10. 初识 Javascript.01 -- Javascript基础|输出方式、变量、变量命名规范、数据类型、
  11. ssm框架之将数据库的数据导入导出为excel文件
  12. 小米5.0以上系统如何没ROOT激活xposed框架的经验
  13. Numpy进阶操作
  14. 树·AVL树/平衡二叉树
  15. mobile_点透_传透_touch-action
  16. Eclipse上传项目到Git
  17. ASP.NET Easyui datagrid增删改+sqlhelper
  18. django之COOKIE 与 SESSION
  19. 粗略的整改一下blog
  20. sharding-jdbc之——分库分表实例

热门文章

  1. java 把json对象中转成map键值对
  2. TestNG简单的学习-TestNG运行
  3. 右键添加在siblime中打开选项
  4. JavaScript 创建对象的几种模式
  5. linux 修改时间
  6. Loadrunner11之VuGen常用函数lr_user_data_point(一)
  7. NSDate相差8小时
  8. 初学spring(二)
  9. POJ 3667 Hotel(线段树)
  10. Linux Tools