从HelloApp看一个cocos2d-x程序是怎么启动的
2013-09-13 22:17
344 查看
初学cocos2d-x,照着别人的示例,稍微改了一些很基础的东西玩玩,例如加些字,加些图片啊什么的。大致了解了,CCScene是个场景类,是被显示的:CCDirector是到导演类,控制程序流程;CCLayer是游戏画面层类,层上可以放置menu、精灵(游戏单位)、其他层等游戏元素。但是我好奇这个程序启动后的流程到底是怎么样的?于是稍微跟踪了一下。
毫无疑问,先main入手。
和QT差不多,基本main都很简单,先是建一个app对象,然后启动app的run()方法。从命名上看,AppDelegate应该是一个继承于CCApplication的类,而
到此,思路很简单,就是新建一个App对象,获取指针(至于为什么不直接用,估计是用断言判断下指针非空什么的,提高安全性吧),然后调用app的run()。那么这个run()里面到底发生了什么?
查看run()函数
,粗略一看,没有create()函数。仔细看,发现一个
添加了按钮
添加图标
添加精灵
到此为止,思路基本理清了,故事原来是这样的:main函数新建了一个app对象并启动了它的run接口;这个run接口呢,调用了一个AppDelegate从CCApplicationProtocol那里继承过来的applicationDidFinishLaunching()接口,在里面新建一个了导演(CCDirector),并且用HelloWorld的scene()接口创建了一个HelloWorld的场景,用导演把场景运行起来,然后就进入按部就班模式(消息循环)。HelloWorld在创建场景的时候呢,就调用了自己的create函数,create里生成了那个场景,至于它场景的布置,则是在init()函数里完成的。
这样整个流程就大致清楚了。我可以在run()接口里对多种消息做处理而不只是退出;让导演多做一些控制,而不只是显示,显示也只是显示一个scene;在init里多加一些游戏元素;等等。
毫无疑问,先main入手。
AppDelegate app; CCEGLView* eglView = CCEGLView::sharedOpenGLView(); eglView->setViewName("HelloCpp"); eglView->setFrameSize(480, 320); return CCApplication::sharedApplication()->run();
和QT差不多,基本main都很简单,先是建一个app对象,然后启动app的run()方法。从命名上看,AppDelegate应该是一个继承于CCApplication的类,而
sharedApplication()这个静态函数也定是返回了app类的指针。转到AppDelegate.h,一看果然是继承于CCApplication。然后查看sharedApplication() 这个函数的定义
CCApplication* CCApplication::sharedApplication() { CC_ASSERT(sm_pSharedApplication); return sm_pSharedApplication; }看了下,基本就是assert()一下,然后返回CCApplication类指针。
到此,思路很简单,就是新建一个App对象,获取指针(至于为什么不直接用,估计是用断言判断下指针非空什么的,提高安全性吧),然后调用app的run()。那么这个run()里面到底发生了什么?
查看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 (!<span style="color: rgb(255, 0, 0);">applicationDidFinishLaunching()</span>) { 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; }发现了一个AppDelegate类中有定义的函数 applicationDidFinishLaunching()。然后下面的结构,一看就是消息循环了,接收msg,处理msg,windows编程也是这个结构,只不过这个例子比较简单,只对一个WM_QUIT做了处理。回过头来查看applicationDidFinishLaunching()这个函数,这函数父类CCApplication并没有,查了下宗谱,发现原来是爷爷的
class CC_DLL CCApplication : public CCApplicationProtocol再看这函数的内容
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; }终于出现了CCDirector、CCScene这些”名“类,也出现了Helloword这个关键字,项目里的另一个类终于出现了。重点在于
CCScene *pScene = HelloWorld::scene(); // run pDirector->runWithScene(pScene);这两句,调用了HelloWorld的一个静态方法获得了一个scene,然后director把运行起来了,然后我们就看到了,事情就是这么简单。继续“转到定义”看scene()这个函数,
CCScene* HelloWorld::scene() { // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object HelloWorld *layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; }创建一个CCScene对象,然后用HelloWorld类的create()函数创建一个“层”,把“层”布置到场景上,返回给导演用。看了下HelloWorld的定义,发现它的基类也是CCLayer
,粗略一看,没有create()函数。仔细看,发现一个
CREATE_FUNC(HelloWorld);点到这个宏上发现正是用这个宏定义这个create()函数,而且还发现这个函数用到了init()函数,正是这个Init()对HelloWorld这个Layer作了修饰,添加了各种图片按钮。
<pre name="code" class="cpp">CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu, 1);
添加了按钮
CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24); // position the label on the center of the screen pLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height)); // add the label as a child to this layer this->addChild(pLabel, 1);
添加图标
CCSprite* pSprite = CCSprite::create("HelloWorld.png"); // position the sprite on the center of the screen pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); // add the sprite as a child to this layer this->addChild(pSprite, 0);
添加精灵
到此为止,思路基本理清了,故事原来是这样的:main函数新建了一个app对象并启动了它的run接口;这个run接口呢,调用了一个AppDelegate从CCApplicationProtocol那里继承过来的applicationDidFinishLaunching()接口,在里面新建一个了导演(CCDirector),并且用HelloWorld的scene()接口创建了一个HelloWorld的场景,用导演把场景运行起来,然后就进入按部就班模式(消息循环)。HelloWorld在创建场景的时候呢,就调用了自己的create函数,create里生成了那个场景,至于它场景的布置,则是在init()函数里完成的。
这样整个流程就大致清楚了。我可以在run()接口里对多种消息做处理而不只是退出;让导演多做一些控制,而不只是显示,显示也只是显示一个scene;在init里多加一些游戏元素;等等。
相关文章推荐
- 一个app的程序是怎么启动的
- android中怎么把自己须要的app启动图标集中到一个弹出框中
- 【iPhone】程序间的通信,程序中启动另外一个app
- 在eclipse程序中设置的断点上有一个斜杠,正常启动debug不能够跳转到debug页面,怎么解决
- Symbian 在一个运行的App中启动安装程序安装另外一个App
- python 怎么启动一个外部命令程序, 并且不阻塞当前进程
- android中怎么把自己需要的app启动图标集中到一个弹出框中
- 怎么判断一个程序正在运行,不能让程序重复启动
- java程序怎么在一个电脑上只启动一次,只开一个进程
- spring启动,做了一个hellojeffen程序。
- 怎么通过代码在一个App当中启动另一个App
- Android系统启动App及 app怎么去启动一个Activity的流程总结
- 【iPhone】程序间的通信,程序中启动另外一个app
- android app启动就闪退怎么办?
- Android 隐藏程序的图标并使用其他APP启动
- C# 自己写了一个windows服务程序,运行时错误: 错误 1053: 服务没有及时响应启动或控制请求。(推荐)
- 怎么用VS2008做一个控制台程序
- 程序只启动一个实例的几种方法
- 一个程序里启动另一一个exe文件
- 用Vim写一个简单的Hello,World程序