微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

cocos2d-x游戏开发(四)游戏主循环

欢迎转载:http://blog.csdn.net/fylz1125/article/details/8518737


终于抽时间把这个游戏写完了。由于没有自拍神器,所以把它移植到了Android上,用我的戴妃跑的很欢啊。自此,我算是完成了一个功能比较完善的游戏了。

麻雀虽小,五脏俱全,该有的都有,不该有的估计也有,嘿嘿。这几天把写这个游戏的经历和学习过程整理一下,多写几篇博客,就当做记笔记了。


首先还是就我个人的理解,讲讲游戏引擎的处理流程。

其实游戏逻辑简单化就是一个死循环,如下:

  1. boolgame_is_running=true;
  2. while(game_is_running){
  3. update_game();
  4. display_game();
  5. }

我们所看到的游戏画面,游戏音乐,以及一些触控,输入等。在逻辑上就是这么一个死循环。这个循环一直在跑,期间会处理一些列的事件,简化之就是上面的两个函数

cocos2d-x引擎也是如此,所有的逻辑都是在这个主循环下实现的。下面看看cocos2dx在各平台上的主循环实现。


1.Win

看它的main.cpp

?
    #include"main.h"
  1. #include"../Classes/AppDelegate.h"
  2. #include"CCEGLView.h"
  3. USING_NS_CC;
  4. intAPIENTRY_tWinMain(HINSTANCEhInstance,
  5. HINSTANCEhPrevInstance,
  6. LPTSTRlpCmdLine,87); font-weight:bold; background-color:inherit">intnCmdshow)
  7. {
  8. UNREFERENCED_ParaMETER(hPrevInstance);
  9. UNREFERENCED_ParaMETER(lpCmdLine);
  10. //createtheapplicationinstance
  11. AppDelegateapp;
  12. CCEGLView*eglView=CCEGLView::sharedOpenGLView();
  13. eglView->setFrameSize(2048,1536);
  14. //Theresolutionofipad3isverylarge.Ingeneral,PC'sresolutionissmallerthanit.
  15. //Soweneedtoinvoke'setFrameZoomFactor'(onlyvalidondesktop(win32,mac,linux))tomakethewindowsmaller.
  16. eglView->setFrameZoomFactor(0.4f);
  17. returnCCApplication::sharedApplication()->run();//注意这里
  18. }

前面都不要关心,只是用来传递OpenGL窗口的,关键是最后一句,CCApplication::sharedApplication()->run()。看这个run函数

?
    intCCApplication::run()
  1. {
  2. PVRFrameEnableControlWindow(false);
  3. //Mainmessageloop:
  4. MSGmsg;
  5. LARGE_INTEGERnFreq;
  6. LARGE_INTEGERnLast;
  7. LARGE_INTEGERnNow;
  8. QueryPerformanceFrequency(&nFreq);
  9. QueryPerformanceCounter(&nLast);
  10. //Initializeinstanceandcocos2d.
  11. if(!applicationDidFinishLaunching())
  12. return0;
  13. }
  14. CCEGLView*pMainWnd=CCEGLView::sharedOpenGLView();
  15. pMainWnd->centerWindow();
  16. ShowWindow(pMainWnd->getHWnd(),SW_SHOW);
  17. while(1)//注意这里,主循环来了
  18. if(!PeekMessage(&msg,NULL,PM_REMOVE))
  19. //Getcurrenttimetick.
  20. QueryPerformanceCounter(&nNow);
  21. //Ifit'sthetimetodrawnextframe,drawit,elsesleepawhile.
  22. if(nNow.QuadPart-nLast.QuadPart>m_nAnimationInterval.QuadPart)
  23. nLast.QuadPart=nNow.QuadPart;
  24. CCDirector::sharedDirector()->mainLoop();//看看这是神马
  25. else
  26. Sleep(0);
  27. continue;
  28. if(WM_QUIT==msg.message)
  29. //Quitmessageloop.
  30. break;
  31. //Dealwithwindowsmessage.
  32. if(!m_hAccelTable||!TranslateAccelerator(msg.hwnd,m_hAccelTable,&msg))
  33. TranslateMessage(&msg);
  34. dispatchMessage(&msg);
  35. }
  36. return(int)msg.wParam;
  37. }

不熟悉windows的童鞋估计都知道windows是消息驱动的。这个死循环就是用来处理windows的消息循环的,在其中处理了FPS逻辑,消息分发等。注意看其中红色标标注的
?
    CCDirector::sharedDirector()->mainLoop();

这是神马东西啊!这个就是cocos2d-x的主循环了,由导演负责维护。从此就进入了cocos2d-x的世界,跟windows没有一毛钱关系了。


2.Android

Android平台的游戏是从一个Activity开始的。(话说好像Android的所有应用都是从Activity开始的吧)。

在引擎源码下有个目录是android的java代码,是模板代码,几乎所有的游戏都用这个,不怎么变。不信可以你可以看

YourCocos2dxDir/cocos2dx/platform/android/java这个目录,就是创建android工程的时候会去这个目录拷贝java代码作为模板。

来看看HelloCpp的代码

[java] ?
    packageorg.cocos2dx.hellocpp;
  1. importorg.cocos2dx.lib.Cocos2dxActivity;
  2. importandroid.os.Bundle;
  3. publicclassHelloCppextendsCocos2dxActivity{
  4. protectedvoidonCreate(BundlesavedInstanceState){
  5. super.onCreate(savedInstanceState);
  6. static{
  7. System.loadLibrary("hellocpp");
  8. }

很简单,对吧。几行代码而已,这里说明了两个问题

1. Cocos2dxActivity才是核心的Activity。

2. 游戏的C++部分包括引擎部分,被编译成了动态链接库hellocpp。这里就是加载了hellocpp动态链接库。

这个动态链接库是在用NDK编译的时候生成的,就是libs/armeabi/libhellocpp.so。(扯远了)


还是来看看Cocos2dxActivity这个Activity。

?
    publicabstractclassCocos2dxActivityextendsActivityimplementsCocos2dxHelperListener{
  1. //===========================================================
  2. //Constants
  3. privatestaticfinalStringTAG=Cocos2dxActivity.class.getSimpleName();
  4. //Fields
  5. privateCocos2dxGLSurfaceViewmGLSurfaceView;//注意这个SurfaceView
  6. privateCocos2dxHandlermHandler;
  7. //===========================================================
  8. //Constructors
  9. @Override
  10. protectedvoidonCreate(finalBundlesavedInstanceState){
  11. super.onCreate(savedInstanceState);
  12. this.mHandler=newCocos2dxHandler(this);
  13. this.init();
  14. Cocos2dxHelper.init(this,this);
  15. //Getter&Setter
  16. //Methodsfor/fromSuperClass/Interfaces
  17. @Override
  18. protectedvoidonResume(){
  19. super.onResume();
  20. Cocos2dxHelper.onResume();
  21. this.mGLSurfaceView.onResume();
  22. protectedvoidonPause(){
  23. super.onPause();
  24. Cocos2dxHelper.onPause();
  25. this.mGLSurfaceView.onPause();
  26. publicvoidshowDialog(finalStringpTitle,finalStringpMessage){
  27. Messagemsg=newMessage();
  28. msg.what=Cocos2dxHandler.HANDLER_SHOW_DIALOG;
  29. msg.obj=newCocos2dxHandler.DialogMessage(pTitle,pMessage);
  30. this.mHandler.sendMessage(msg);
  31. publicvoidshowEditTextDialog(finalStringpTitle,finalStringpContent,finalintpInputMode,finalintpInputFlag,finalintpReturnType,finalintpMaxLength){
  32. msg.what=Cocos2dxHandler.HANDLER_SHOW_EDITBox_DIALOG;
  33. msg.obj=newCocos2dxHandler.EditBoxMessage(pTitle,pContent,pInputMode,pInputFlag,pReturnType,pMaxLength);
  34. publicvoidrunOnGLThread(finalRunnablepRunnable){
  35. this.mGLSurfaceView.queueEvent(pRunnable);
  36. //Methods
  37. publicvoidinit(){
  38. //FrameLayout
  39. ViewGroup.LayoutParamsframelayout_params=
  40. newViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,153); list-style:decimal-leading-zero outside; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important"> ViewGroup.LayoutParams.FILL_PARENT);
  41. FrameLayoutframelayout=newFrameLayout(this);//帧布局,可一层一层覆盖
  42. framelayout.setLayoutParams(framelayout_params);
  43. //Cocos2dxEditTextlayout
  44. ViewGroup.LayoutParamsedittext_layout_params=
  45. newViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,248)"> ViewGroup.LayoutParams.WRAP_CONTENT);
  46. Cocos2dxEditTextedittext=newCocos2dxEditText(this);
  47. edittext.setLayoutParams(edittext_layout_params);
  48. //...addtoFrameLayout
  49. framelayout.addView(edittext);
  50. //Cocos2dxGLSurfaceView
  51. this.mGLSurfaceView=this.onCreateView();
  52. framelayout.addView(this.mGLSurfaceView);//添加GLSurfaceView
  53. this.mGLSurfaceView.setCocos2dxRenderer(newCocos2dxRenderer());//意这行,一个渲染器
  54. this.mGLSurfaceView.setCocos2dxEditText(edittext);
  55. //Setframelayoutasthecontentview
  56. setContentView(framelayout);
  57. publicCocos2dxGLSurfaceViewonCreateView(){
  58. returnnewCocos2dxGLSurfaceView(this);
  59. //InnerandAnonymousClasses
  60. }

代码很多,呵呵。其实核心就是那个mGLSurfaceView和它的渲染器new Cocos2dxRenderer()。在Android上,OpenGL的渲染是由一个GLSurfaceView和其渲染器Render组成。GLSurfaceView显示界面,Render渲染更新。这个Render其实是一个渲染线程,不停再跑,由框架层维护。这里不多讲。

来看这个Cocos2dxRenderer

?
    packageorg.cocos2dx.lib;
  1. importjavax.microedition.khronos.egl.EGLConfig;
  2. importjavax.microedition.khronos.opengles.GL10;
  3. importandroid.opengl.GLSurfaceView;
  4. publicclassCocos2dxRendererimplementsGLSurfaceView.Renderer{
  5. //Constants
  6. privatefinalstaticlongNANOSECONDSPERSECOND=1000000000L;
  7. privatefinalstaticlongNANOSECONDSPERMICROSECOND=1000000;
  8. privatestaticlongsAnimationInterval=(long)(1.0/60*Cocos2dxRenderer.NANOSECONDSPERSECOND);
  9. privatelongmLastTickInNanoSeconds;
  10. privateintmScreenWidth;
  11. privateintmScreenHeight;
  12. //Constructors
  13. publicstaticvoidsetAnimationInterval(finaldoublepAnimationInterval){
  14. Cocos2dxRenderer.sAnimationInterval=(long)(pAnimationInterval*Cocos2dxRenderer.NANOSECONDSPERSECOND);
  15. publicvoidsetScreenWidthAndHeight(finalintpSurfaceWidth,finalintpSurfaceHeight){
  16. this.mScreenWidth=pSurfaceWidth;
  17. this.mScreenHeight=pSurfaceHeight;
  18. //Methodsfor/fromSuperClass/Interfaces
  19. @Override//①注意这里
  20. publicvoidonSurfaceCreated(finalGL10pGL10,finalEGLConfigpEGLConfig){
  21. Cocos2dxRenderer.nativeInit(this.mScreenWidth,this.mScreenHeight);//②初始化窗口
  22. this.mLastTickInNanoSeconds=System.nanoTime();
  23. publicvoidonSurfaceChanged(finalGL10pGL10,finalintpWidth,finalintpHeight){
  24. //③注意这里
  25. publicvoidonDrawFrame(finalGL10gl){
  26. /*
  27. *FPScontrollingalgorithmisnotaccurate,anditwillslowdownFPS
  28. *onsomedevices.socommentFPScontrollingcode.
  29. */
  30. /*
  31. finallongNowInNanoSeconds=System.nanoTime();
  32. finallonginterval=NowInNanoSeconds-this.mLastTickInNanoSeconds;
  33. */
  34. //shouldrenderaframewhenonDrawFrame()iscalledorthereisa
  35. //"ghost"
  36. Cocos2dxRenderer.nativeRender();//④特别注意这个
  37. //fpscontrolling
  38. if(interval<Cocos2dxRenderer.sAnimationInterval){
  39. try{
  40. //becausewerenderitbefore,soweshouldsleeptwicetimeinterval
  41. Thread.sleep((Cocos2dxRenderer.sAnimationInterval-interval)/Cocos2dxRenderer.NANOSECONDSPERMICROSECOND);
  42. }catch(finalExceptione){
  43. }
  44. }
  45. this.mLastTickInNanoSeconds=NowInNanoSeconds;
  46. //Methods
  47. privatestaticnativevoidnativetouchesBegin(finalintpID,finalfloatpX,finalfloatpY);
  48. privatestaticnativevoidnativetouchesEnd(finalintpID,finalfloatpY);
  49. privatestaticnativevoidnativetouchesMove(finalint[]pIDs,finalfloat[]pXs,finalfloat[]pYs);
  50. privatestaticnativevoidnativetouchesCancel(finalint[]pIDs,finalfloat[]pYs);
  51. privatestaticnativebooleannativeKeyDown(finalintpKeyCode);
  52. privatestaticnativevoidnativeRender();
  53. privatestaticnativevoidnativeInit(finalintpWidth,finalintpHeight);
  54. privatestaticnativevoidnativeOnPause();
  55. privatestaticnativevoidnativeOnResume();
  56. publicvoidhandleActionDown(finalintpID,finalfloatpY){
  57. Cocos2dxRenderer.nativetouchesBegin(pID,pX,pY);
  58. publicvoidhandleActionUp(finalintpID,153); list-style:decimal-leading-zero outside; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important"> Cocos2dxRenderer.nativetouchesEnd(pID,248)"> publicvoidhandleActionCancel(finalint[]pIDs,finalfloat[]pYs){
  59. Cocos2dxRenderer.nativetouchesCancel(pIDs,pXs,pYs);
  60. publicvoidhandleActionMove(finalint[]pIDs,153); list-style:decimal-leading-zero outside; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important"> Cocos2dxRenderer.nativetouchesMove(pIDs,248)"> publicvoidhandleKeyDown(finalintpKeyCode){
  61. Cocos2dxRenderer.nativeKeyDown(pKeyCode);
  62. publicvoidhandleOnPause(){
  63. Cocos2dxRenderer.nativeOnPause();
  64. publicvoidhandleOnResume(){
  65. Cocos2dxRenderer.nativeOnResume();
  66. privatestaticnativevoidnativeInsertText(finalStringpText);
  67. privatestaticnativevoidnativeDeleteBackward();
  68. privatestaticnativeStringnativeGetContentText();
  69. publicvoidhandleInsertText(finalStringpText){
  70. Cocos2dxRenderer.nativeInsertText(pText);
  71. publicvoidhandleDeleteBackward(){
  72. Cocos2dxRenderer.nativeDeleteBackward();
  73. publicStringgetContentText(){
  74. returnCocos2dxRenderer.nativeGetContentText();
  75. }

代码很多,一副貌似很复杂的样子。其实脉络很清晰的,我们只看脉络,不考虑细节哈。我们顺藤摸瓜来...

首先要知道GLSurfaceView的渲染器必须实现GLSurfaceView.Renderer接口。就是上面的三个Override方法

onSurfaceCreated在窗口建立的时候调用,onSurfaceChanged在窗口建立和大小变化是调用,onDrawFrame这个方法就跟普通View的Ondraw方法一样,窗口建立初始化完成后渲染线程不停的调这个方法。这些都是框架决定的,就是这个样子。下面分析下代码几处标记的地方:

标记,窗口建立,这个时候要进行初始化。这个时候它调用一个native函数,就是标记。看到这个函数形式是不是能想到什么呢,等下再说。

标记,前面说了,这个函数会被渲染线程不停调用像不像主循环的死循环啊)。然后里面有个很牛擦的函数

这又是一个native的函数,呵呵。

native的代码是神马啊,就是C++啊。知之为知之,不知谷歌之。

既然是java调用C++,那就是jni调用了。

我们来看看jni/hellocpp/下的main.cpp

?
    #include"AppDelegate.h"
  1. #include"platform/android/jni/JniHelper.h"
  2. #include<jni.h>
  3. #include<android/log.h>
  4. #include"HelloWorldScene.h"
  5. #defineLOG_TAG"main"
  6. #defineLOGD(...)__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
  7. usingnamespacecocos2d;
  8. extern"C"
  9. jintJNI_OnLoad(JavaVM*vm,void*reserved)
  10. JniHelper::setJavaVM(vm);
  11. returnJNI_VERSION_1_4;
  12. voidJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(jnienv*env,jobjectthiz,jintw,jinth)
  13. if(!CCDirector::sharedDirector()->getopenGLView())
  14. CCEGLView*view=CCEGLView::sharedOpenGLView();
  15. view->setFrameSize(w,h);
  16. cclog("with%d,height%d",w,h);
  17. AppDelegate*pAppDelegate=newAppDelegate();
  18. CCApplication::sharedApplication()->run();//看这里⑤
  19. else
  20. ccDrawInit();
  21. ccGLInvalidateStateCache();
  22. CCshadercache::sharedshadercache()->reloadDefaultShaders();
  23. CCTextureCache::reloadAllTextures();
  24. CCNotificationCenter::sharednotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND,NULL);
  25. CCDirector::sharedDirector()->setGLDefaultValues();
  26. }

根据Jni的命名规则,那个标注的nativeInit方法就是上面红色一长串(呵呵)。窗口建立起来后调用nativeInit方法,就是调用这个C++的实现。这里做了窗口的初始化处理。

看标注,你以为这个run函数就进入主循环了么,呵呵

看这个run

?
    <spanstyle="font-size:18px;">//Initializeinstanceandcocos2d.
  1. if(!applicationDidFinishLaunching())
  2. return0;
  3. return-1;
  4. }</span>

我们看到了神马!实质上就调了一下applicationDidFinishLaunching,别的什么也没干。所以这里没有进入主循环。

现在再看。这个逻辑貌似就是主循环。

这个nativeRender()函数的实现在Yourcocos2dDir/cocos2dx/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp

?
    #include"text_input_node/CCIMEdispatcher.h"
  1. #include"CCDirector.h"
  2. #include"../CCApplication.h"
  3. #include"platform/CCFileUtils.h"
  4. #include"CCEventType.h"
  5. #include"support/CCNotificationCenter.h"
  6. #include"JniHelper.h"
  7. #include<jni.h>
  8. usingnamespacecocos2d;
  9. extern"C"{
  10. JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_<spanstyle="color:#ff0000;">Cocos2dxRenderer_nativeRender</span>(jnienv*env){
  11. <spanstyle="color:#ff0000;">cocos2d::CCDirector::sharedDirector()->mainLoop();//看到木有,这是什么</span>
  12. JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause(){
  13. CCApplication::sharedApplication()->applicationDidEnterBackground();
  14. CCNotificationCenter::sharednotificationCenter()->postNotification(EVENT_COME_TO_BACKGROUND,NULL);
  15. JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume(){
  16. if(CCDirector::sharedDirector()->getopenGLView()){
  17. CCApplication::sharedApplication()->applicationWillEnterForeground();
  18. JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeInsertText(jnienv*env,jstringtext){
  19. constchar*pszText=env->GetStringUTFChars(text,NULL);
  20. cocos2d::CCIMEdispatcher::shareddispatcher()->dispatchInsertText(pszText,strlen(pszText));
  21. env->ReleaseStringUTFChars(text,pszText);
  22. JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeDeleteBackward(jnienv*env,jobjectthiz){
  23. cocos2d::CCIMEdispatcher::shareddispatcher()->dispatchDeleteBackward();
  24. JNIEXPORTjstringJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeGetContentText(){
  25. jnienv*env=0;
  26. if(JniHelper::getJavaVM()->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK||!env){
  27. constchar*pszText=cocos2d::CCIMEdispatcher::shareddispatcher()->getContentText();
  28. returnenv->NewStringUTF(pszText);
  29. }

看上面标注,找到导演了,导演又开始主循环了。真是众里寻他千百度,那人却在灯火阑珊处啊。

到这里可以发现,Android上的主循环跟win上的不太一样,它不是一个简单的while就完了。它是由java的渲染线程发起的,通过不断调用render来驱动。


3.iOs

ios上面和Android上类似。看AppController.mm

?
    #import<UIKit/UIKit.h>
  1. #import"AppController.h"
  2. #import"cocos2d.h"
  3. #import"EAGLView.h"
  4. #import"AppDelegate.h"
  5. #import"RootViewController.h"
  6. @implementationAppController
  7. @synthesizewindow;
  8. @synthesizeviewController;
  9. #pragmamark-
  10. #pragmamarkApplicationlifecycle
  11. //cocos2dapplicationinstance
  12. staticAppDelegates_sharedApplication;
  13. -(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{
  14. //Overridepointforcustomizationafterapplicationlaunch.
  15. //Addtheviewcontroller'sviewtothewindowanddisplay.
  16. window=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];
  17. EAGLView*__glView=[EAGLViewviewWithFrame:[windowbounds]
  18. pixelFormat:kEAGLColorFormatRGBA8
  19. depthFormat:GL_DEPTH_COMPONENT16
  20. preserveBackbuffer:NO
  21. sharegroup:nil
  22. multiSampling:NO
  23. numberOfSamples:0];
  24. //UseRootViewControllermanageEAGLView
  25. viewController=[[RootViewControlleralloc]initWithNibName:nilbundle:nil];
  26. viewController.wantsFullScreenLayout=YES;
  27. viewController.view=__glView;
  28. //SetRootViewControllertowindow
  29. if([[UIDevicecurrentDevice].systemVersionfloatValue]<6.0)
  30. //warning:addSubViewdoesn'tworkoniOS6
  31. [windowaddSubview:viewController.view];
  32. //usethismethodonios6
  33. [windowsetRootViewController:viewController];
  34. [windowmakeKeyAndVisible];
  35. [[UIApplicationsharedApplication]setStatusBarHidden:YES];
  36. <spanstyle="color:#ff0000;">cocos2d::CCApplication::sharedApplication()->run();</span>//<spanstyle="color:#ff0000;">看这里</span>
  37. returnYES;
  38. -(void)applicationWillResignActive:(UIApplication*)application{
  39. Sentwhentheapplicationisabouttomovefromactivetoinactivestate.Thiscanoccurforcertaintypesoftemporaryinterruptions(suchasanincomingphonecallorSMSmessage)orwhentheuserquitstheapplicationanditbeginsthetransitiontothebackgroundstate.
  40. UsethismethodtopauSEOngoingtasks,disabletimers,andthrottledownopenGLESframerates.Gamesshouldusethismethodtopausethegame.
  41. cocos2d::CCDirector::sharedDirector()->pause();
  42. -(void)applicationDidBecomeActive:(UIApplication*)application{
  43. Restartanytasksthatwerepaused(ornotyetstarted)whiletheapplicationwasinactive.IftheapplicationwasprevIoUslyinthebackground,optionallyrefreshtheuserinterface.
  44. cocos2d::CCDirector::sharedDirector()->resume();
  45. -(void)applicationDidEnterBackground:(UIApplication*)application{
  46. Usethismethodtoreleasesharedresources,saveuserdata,invalidatetimers,andstoreenoughapplicationstateinformationtorestoreyourapplicationtoitscurrentstateincaseitisterminatedlater.
  47. Ifyourapplicationsupportsbackgroundexecution,calledinsteadofapplicationWillTerminate:whentheuserquits.
  48. cocos2d::CCApplication::sharedApplication()->applicationDidEnterBackground();
  49. -(void)applicationWillEnterForeground:(UIApplication*)application{
  50. Calledaspartoftransitionfromthebackgroundtotheinactivestate:hereyoucanundomanyofthechangesmadeonenteringthebackground.
  51. cocos2d::CCApplication::sharedApplication()->applicationWillEnterForeground();
  52. -(void)applicationWillTerminate:(UIApplication*)application{
  53. Calledwhentheapplicationisabouttoterminate.
  54. SeealsoapplicationDidEnterBackground:.
  55. #pragmamark-
  56. #pragmamarkMemorymanagement
  57. -(void)applicationDidReceiveMemoryWarning:(UIApplication*)application{
  58. Freeupasmuchmemoryaspossiblebypurgingcacheddataobjectsthatcanberecreated(orreloadedfromdisk)later.
  59. cocos2d::CCDirector::sharedDirector()->purgeCachedData();
  60. -(void)dealloc{
  61. [superdealloc];
  62. @end

直接看标注,跟进run()

?
    if(applicationDidFinishLaunching())
  1. <spanstyle="color:#ff0000;">[[CCDirectorCallersharedDirectorCaller]startMainLoop]</span>;
  2. }</span>
再跟标注的startMainLoop()

?
    -(void)startMainLoop
  1. //CCDirector::setAnimationInterval()iscalled,weshouldinvalidateitfirst
  2. [displayLinkinvalidate];
  3. displayLink=nil;
  4. NSLog(@"runloop!");
  5. displayLink=[NSClassFromString(@"CAdisplayLink")displayLinkWithTarget:selfselector:@selector(doCaller:)];//看这里
  6. [displayLinksetFrameInterval:self.interval];
  7. [displayLinkaddToRunLoop:[NSRunLoopcurrentRunLoop]forMode:NSDefaultRunLoopMode];
  8. }
好了,看红色标注。这个貌似循环不起来啊,呵呵。

仔细看他加载的这个类CAdisplayLink,就是这个东西循环起来的。这其实就是个定时器,认每秒运行60次,其有个属性可以设置FPS。看后面有个回调函数doCaller,跟进

?
    -(void)doCaller:(id)sender
  1. cocos2d::CCDirector::sharedDirector()->mainLoop(); }
好了,终于又看到导演了。导演很忙,又开始主循环了。


一旦进入主循环,游戏就开始我们自己设计的游戏逻辑。

打字打的睡着了....不打了

原文地址:https://www.jb51.cc/cocos2dx/342238.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐