cocos2d-x游戏开发(四)游戏主循环
前端之家收集整理的这篇文章主要介绍了
cocos2d-x游戏开发(四)游戏主循环,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
欢迎转载:http://blog.csdn.net/fylz1125/article/details/8518737
终于抽时间把这个游戏写完了。由于没有自拍神器,所以把它移植到了Android上,用我的戴妃跑的很欢啊。自此,我算是完成了一个功能比较完善的游戏了。
麻雀虽小,五脏俱全,该有的都有,不该有的估计也有,嘿嘿。这几天把写这个游戏的经历和学习过程整理一下,多写几篇博客,就当做记笔记了。
首先还是就我个人的理解,讲讲游戏引擎的处理流程。
其实游戏逻辑简单化就是一个死循环,如下:
- @H_301_47@
- boolgame_is_running=true;@H_301_47@
- @H_301_47@
- while(game_is_running){@H_301_47@
- update_game();@H_301_47@
- display_game();@H_301_47@
- }@H_301_47@
我们所看到的游戏画面,游戏音乐,以及一些触控,输入等。在逻辑上就是这么一个死循环。这个循环一直在跑,期间会处理一些列的事件,简化之就是上面的两个函数。
cocos2d-x引擎也是如此,所有的逻辑都是在这个主循环下实现的。下面看看cocos2dx在各平台上的主循环实现。
1.Win
看它的main.cpp
#include"main.h"@H_301_47@
- #include"../Classes/AppDelegate.h"@H_301_47@
- #include"CCEGLView.h"@H_301_47@
- @H_301_47@
- USING_NS_CC;@H_301_47@
- intAPIENTRY_tWinMain(HINSTANCEhInstance,@H_301_47@
- HINSTANCEhPrevInstance,@H_301_47@
- LPTSTRlpCmdLine,87); font-weight:bold; background-color:inherit">intnCmdShow)@H_301_47@
- {@H_301_47@
- UNREFERENCED_PARAMETER(hPrevInstance);@H_301_47@
- UNREFERENCED_PARAMETER(lpCmdLine);@H_301_47@
- @H_301_47@
- AppDelegateapp;@H_301_47@
- CCEGLView*eglView=CCEGLView::sharedOpenGLView();@H_301_47@
- eglView->setFrameSize(2048,1536);@H_301_47@
- //Theresolutionofipad3isverylarge.Ingeneral,PC'sresolutionissmallerthanit.@H_301_47@
- @H_301_47@
- eglView->setFrameZoomFactor(0.4f);@H_301_47@
- returnCCApplication::sharedApplication()->run();@H_301_47@
- }@H_301_47@
前面都不要关心,只是用来传递OpenGL窗口的,关键是最后一句,CCApplication::sharedApplication()->run()。看这个run函数:
intCCApplication::run()@H_301_47@
- {@H_301_47@
- PVRFrameEnableControlWindow(false);@H_301_47@
- //Mainmessageloop:@H_301_47@
- MSGmsg;@H_301_47@
- LARGE_INTEGERnFreq;@H_301_47@
- LARGE_INTEGERnLast;@H_301_47@
- LARGE_INTEGERnNow;@H_301_47@
- QueryPerformanceFrequency(&nFreq);@H_301_47@
- QueryPerformanceCounter(&nLast);@H_301_47@
- //Initializeinstanceandcocos2d.@H_301_47@
- if(!applicationDidFinishLaunching())@H_301_47@
- return0;@H_301_47@
- }@H_301_47@
- CCEGLView*pMainWnd=CCEGLView::sharedOpenGLView();@H_301_47@
- pMainWnd->centerWindow();@H_301_47@
- ShowWindow(pMainWnd->getHWnd(),SW_SHOW);@H_301_47@
- while(1)@H_301_47@
- if(!PeekMessage(&msg,NULL,PM_REMOVE))@H_301_47@
- //Getcurrenttimetick.@H_301_47@
- QueryPerformanceCounter(&nNow);@H_301_47@
- //Ifit'sthetimetodrawnextframe,drawit,elsesleepawhile.@H_301_47@
- if(nNow.QuadPart-nLast.QuadPart>m_nAnimationInterval.QuadPart)@H_301_47@
- nLast.QuadPart=nNow.QuadPart;@H_301_47@
- CCDirector::sharedDirector()->mainLoop();@H_301_47@
- else@H_301_47@
- Sleep(0);@H_301_47@
- continue;@H_301_47@
- if(WM_QUIT==msg.message)@H_301_47@
- //Quitmessageloop.@H_301_47@
- break;@H_301_47@
- //Dealwithwindowsmessage.@H_301_47@
- if(!m_hAccelTable||!TranslateAccelerator(msg.hwnd,m_hAccelTable,&msg))@H_301_47@
- TranslateMessage(&msg);@H_301_47@
- DispatchMessage(&msg);@H_301_47@
- }@H_301_47@
- return(int)msg.wParam;@H_301_47@
- }@H_301_47@
不熟悉windows的童鞋估计都知道windows是消息驱动的。这个死循环就是用来处理windows的消息循环的,在其中处理了FPS逻辑,消息分发等。注意看其中红色标标注的
CCDirector::sharedDirector()->mainLoop();@H_301_47@
这是神马东西啊!这个就是cocos2d-x的主循环了,由导演负责维护。从此就进入了cocos2d-x的世界,跟windows没有一毛钱关系了。
2.Android
Android平台的游戏是从一个Activity开始的。(话说好像Android的所有应用都是从Activity开始的吧)。
在引擎源码下有个目录是android的java代码,是模板代码,几乎所有的游戏都用这个,不怎么变。不信可以你可以看
YourCocos2dxDir/cocos2dx/platform/android/java这个目录,就是创建android工程的时候会去这个目录拷贝java代码作为模板。
来看看HelloCpp的代码
packageorg.cocos2dx.hellocpp;@H_301_47@
- importorg.cocos2dx.lib.Cocos2dxActivity;@H_301_47@
- importandroid.os.Bundle;@H_301_47@
- publicclassHelloCppextendsCocos2dxActivity{@H_301_47@
- protectedvoidonCreate(BundlesavedInstanceState){@H_301_47@
- super.onCreate(savedInstanceState);@H_301_47@
- static{@H_301_47@
- System.loadLibrary("hellocpp");@H_301_47@
- }@H_301_47@
很简单,对吧。几行代码而已,这里说明了两个问题
1. Cocos2dxActivity才是核心的Activity。
2. 游戏的C++部分包括引擎部分,被编译成了动态链接库hellocpp。这里就是加载了hellocpp动态链接库。
这个动态链接库是在用NDK编译的时候生成的,就是libs/armeabi/libhellocpp.so。(扯远了)
还是来看看Cocos2dxActivity这个Activity。
publicabstractclassCocos2dxActivityextendsActivityimplementsCocos2dxHelperListener{@H_301_47@
- //===========================================================@H_301_47@
- //Constants@H_301_47@
- privatestaticfinalStringTAG=Cocos2dxActivity.class.getSimpleName();@H_301_47@
- //Fields@H_301_47@
- privateCocos2dxGLSurfaceViewmGLSurfaceView;@H_301_47@
- privateCocos2dxHandlermHandler;@H_301_47@
- //===========================================================@H_301_47@
- //Constructors@H_301_47@
- @Override@H_301_47@
- protectedvoidonCreate(finalBundlesavedInstanceState){@H_301_47@
- super.onCreate(savedInstanceState);@H_301_47@
- this.mHandler=newCocos2dxHandler(this);@H_301_47@
- this.init();@H_301_47@
- Cocos2dxHelper.init(this,this);@H_301_47@
- //Getter&Setter@H_301_47@
- //Methodsfor/fromSuperClass/Interfaces@H_301_47@
- @Override@H_301_47@
- protectedvoidonResume(){@H_301_47@
- super.onResume();@H_301_47@
- Cocos2dxHelper.onResume();@H_301_47@
- this.mGLSurfaceView.onResume();@H_301_47@
- protectedvoidonPause(){@H_301_47@
- super.onPause();@H_301_47@
- Cocos2dxHelper.onPause();@H_301_47@
- this.mGLSurfaceView.onPause();@H_301_47@
- publicvoidshowDialog(finalStringpTitle,finalStringpMessage){@H_301_47@
- Messagemsg=newMessage();@H_301_47@
- msg.what=Cocos2dxHandler.HANDLER_SHOW_DIALOG;@H_301_47@
- msg.obj=newCocos2dxHandler.DialogMessage(pTitle,pMessage);@H_301_47@
- this.mHandler.sendMessage(msg);@H_301_47@
- publicvoidshowEditTextDialog(finalStringpTitle,finalStringpContent,finalintpInputMode,finalintpInputFlag,finalintpReturnType,finalintpMaxLength){@H_301_47@
- msg.what=Cocos2dxHandler.HANDLER_SHOW_EDITBox_DIALOG;@H_301_47@
- msg.obj=newCocos2dxHandler.EditBoxMessage(pTitle,pContent,pInputMode,pInputFlag,pReturnType,pMaxLength);@H_301_47@
- publicvoidrunOnGLThread(finalRunnablepRunnable){@H_301_47@
- this.mGLSurfaceView.queueEvent(pRunnable);@H_301_47@
- //Methods@H_301_47@
- publicvoidinit(){@H_301_47@
- //FrameLayout@H_301_47@
- ViewGroup.LayoutParamsframelayout_params=@H_301_47@
- 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);@H_301_47@
- FrameLayoutframelayout=newFrameLayout(this);@H_301_47@
- framelayout.setLayoutParams(framelayout_params);@H_301_47@
- //Cocos2dxEditTextlayout
@H_301_47@
- ViewGroup.LayoutParamsedittext_layout_params=@H_301_47@
- newViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,248)"> ViewGroup.LayoutParams.WRAP_CONTENT);@H_301_47@
- Cocos2dxEditTextedittext=newCocos2dxEditText(this);@H_301_47@
- edittext.setLayoutParams(edittext_layout_params);@H_301_47@
- //...addtoFrameLayout
@H_301_47@
- framelayout.addView(edittext);@H_301_47@
- //Cocos2dxGLSurfaceView@H_301_47@
- this.mGLSurfaceView=this.onCreateView();@H_301_47@
- framelayout.addView(this.mGLSurfaceView);@H_301_47@
- this.mGLSurfaceView.setCocos2dxRenderer(newCocos2dxRenderer());@H_301_47@
- this.mGLSurfaceView.setCocos2dxEditText(edittext);@H_301_47@
- //Setframelayoutasthecontentview@H_301_47@
- setContentView(framelayout);@H_301_47@
- publicCocos2dxGLSurfaceViewonCreateView(){@H_301_47@
- returnnewCocos2dxGLSurfaceView(this);@H_301_47@
- //InnerandAnonymousClasses@H_301_47@
- }@H_301_47@
代码很多,呵呵。其实核心就是那个mGLSurfaceView和它的渲染器new Cocos2dxRenderer()。在Android上,OpenGL的渲染是由一个GLSurfaceView和其渲染器Render组成。GLSurfaceView显示界面,Render渲染更新。这个Render其实是一个渲染线程,不停再跑,由框架层维护。这里不多讲。
来看这个Cocos2dxRenderer
packageorg.cocos2dx.lib;@H_301_47@
- importjavax.microedition.khronos.egl.EGLConfig;@H_301_47@
- importjavax.microedition.khronos.opengles.GL10;@H_301_47@
- importandroid.opengl.GLSurfaceView;@H_301_47@
- publicclassCocos2dxRendererimplementsGLSurfaceView.Renderer{@H_301_47@
- //Constants@H_301_47@
- privatefinalstaticlongNANOSECONDSPERSECOND=1000000000L;@H_301_47@
- privatefinalstaticlongNANOSECONDSPERMICROSECOND=1000000;@H_301_47@
- privatestaticlongsAnimationInterval=(long)(1.0/60*Cocos2dxRenderer.NANOSECONDSPERSECOND);@H_301_47@
- privatelongmLastTickInNanoSeconds;@H_301_47@
- privateintmScreenWidth;@H_301_47@
- privateintmScreenHeight;@H_301_47@
- //Constructors@H_301_47@
- publicstaticvoidsetAnimationInterval(finaldoublepAnimationInterval){@H_301_47@
- Cocos2dxRenderer.sAnimationInterval=(long)(pAnimationInterval*Cocos2dxRenderer.NANOSECONDSPERSECOND);@H_301_47@
- publicvoidsetScreenWidthAndHeight(finalintpSurfaceWidth,finalintpSurfaceHeight){@H_301_47@
- this.mScreenWidth=pSurfaceWidth;@H_301_47@
- this.mScreenHeight=pSurfaceHeight;@H_301_47@
- //Methodsfor/fromSuperClass/Interfaces@H_301_47@
- @Override@H_301_47@
- publicvoidonSurfaceCreated(finalGL10pGL10,finalEGLConfigpEGLConfig){@H_301_47@
- Cocos2dxRenderer.nativeInit(this.mScreenWidth,this.mScreenHeight);@H_301_47@
- this.mLastTickInNanoSeconds=System.nanoTime();@H_301_47@
- publicvoidonSurfaceChanged(finalGL10pGL10,finalintpWidth,finalintpHeight){@H_301_47@
- //③注意这里@H_301_47@
- publicvoidonDrawFrame(finalGL10gl){@H_301_47@
- /*@H_301_47@
- *FPScontrollingalgorithmisnotaccurate,anditwillslowdownFPS@H_301_47@
- *onsomedevices.SocommentFPScontrollingcode.@H_301_47@
- */@H_301_47@
- /*@H_301_47@
- finallongnowInNanoSeconds=System.nanoTime();@H_301_47@
- finallonginterval=nowInNanoSeconds-this.mLastTickInNanoSeconds;@H_301_47@
- */@H_301_47@
- //shouldrenderaframewhenonDrawFrame()iscalledorthereisa@H_301_47@
- //"ghost"@H_301_47@
- Cocos2dxRenderer.nativeRender();@H_301_47@
- //fpscontrolling@H_301_47@
- if(interval<Cocos2dxRenderer.sAnimationInterval){@H_301_47@
- try{@H_301_47@
- //becausewerenderitbefore,soweshouldsleeptwicetimeinterval@H_301_47@
- Thread.sleep((Cocos2dxRenderer.sAnimationInterval-interval)/Cocos2dxRenderer.NANOSECONDSPERMICROSECOND);@H_301_47@
- }catch(finalExceptione){@H_301_47@
- }@H_301_47@
- }@H_301_47@
- @H_301_47@
- this.mLastTickInNanoSeconds=nowInNanoSeconds;@H_301_47@
- //Methods@H_301_47@
- privatestaticnativevoidnativeTouchesBegin(finalintpID,finalfloatpX,finalfloatpY);@H_301_47@
- privatestaticnativevoidnativeTouchesEnd(finalintpID,finalfloatpY);@H_301_47@
- privatestaticnativevoidnativeTouchesMove(finalint[]pIDs,finalfloat[]pXs,finalfloat[]pYs);@H_301_47@
- privatestaticnativevoidnativeTouchesCancel(finalint[]pIDs,finalfloat[]pYs);@H_301_47@
- privatestaticnativebooleannativeKeyDown(finalintpKeyCode);@H_301_47@
- privatestaticnativevoidnativeRender();@H_301_47@
- privatestaticnativevoidnativeInit(finalintpWidth,finalintpHeight);@H_301_47@
- privatestaticnativevoidnativeOnPause();@H_301_47@
- privatestaticnativevoidnativeOnResume();@H_301_47@
- publicvoidhandleActionDown(finalintpID,finalfloatpY){@H_301_47@
- Cocos2dxRenderer.nativeTouchesBegin(pID,pX,pY);@H_301_47@
- 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){@H_301_47@
- Cocos2dxRenderer.nativeTouchesCancel(pIDs,pXs,pYs);@H_301_47@
- 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){@H_301_47@
- Cocos2dxRenderer.nativeKeyDown(pKeyCode);@H_301_47@
- publicvoidhandleOnPause(){@H_301_47@
- Cocos2dxRenderer.nativeOnPause();@H_301_47@
- publicvoidhandleOnResume(){@H_301_47@
- Cocos2dxRenderer.nativeOnResume();@H_301_47@
- privatestaticnativevoidnativeInsertText(finalStringpText);@H_301_47@
- privatestaticnativevoidnativeDeleteBackward();@H_301_47@
- privatestaticnativeStringnativeGetContentText();@H_301_47@
- publicvoidhandleInsertText(finalStringpText){@H_301_47@
- Cocos2dxRenderer.nativeInsertText(pText);@H_301_47@
- publicvoidhandleDeleteBackward(){@H_301_47@
- Cocos2dxRenderer.nativeDeleteBackward();@H_301_47@
- publicStringgetContentText(){@H_301_47@
- returnCocos2dxRenderer.nativeGetContentText();@H_301_47@
- }@H_301_47@
代码很多,一副貌似很复杂的样子。其实脉络很清晰的,我们只看脉络,不考虑细节哈。我们顺藤摸瓜来...
首先要知道GLSurfaceView的渲染器必须实现GLSurfaceView.Renderer接口。就是上面的三个Override方法。
onSurfaceCreated在窗口建立的时候调用,onSurfaceChanged在窗口建立和大小变化是调用,onDrawFrame这个方法就跟普通View的Ondraw方法一样,窗口建立初始化完成后渲染线程不停的调这个方法。这些都是框架决定的,就是这个样子。下面分析下代码几处标记的地方:
看标记①,窗口建立,这个时候要进行初始化。这个时候它调用了一个native函数,就是标记②。看到这个函数形式是不是能想到什么呢,等下再说。
看标记③,前面说了,这个函数会被渲染线程不停调用(像不像主循环的死循环啊)。然后里面有个很牛擦的函数④。
这又是一个native的函数,呵呵。
native的代码是神马啊,就是C++啊。知之为知之,不知谷歌之。
既然是java调用C++,那就是jni调用了。
我们来看看jni/hellocpp/下的main.cpp
#include"AppDelegate.h"@H_301_47@
- #include"platform/android/jni/JniHelper.h"@H_301_47@
- #include<jni.h>@H_301_47@
- #include<android/log.h>@H_301_47@
- #include"HelloWorldScene.h"@H_301_47@
- #defineLOG_TAG"main"@H_301_47@
- #defineLOGD(...)__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)@H_301_47@
- usingnamespacecocos2d;@H_301_47@
- extern"C"@H_301_47@
- jintJNI_OnLoad(JavaVM*vm,void*reserved)@H_301_47@
- JniHelper::setJavaVM(vm);@H_301_47@
- returnJNI_VERSION_1_4;@H_301_47@
- voidJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv*env,jobjectthiz,jintw,jinth)@H_301_47@
- if(!CCDirector::sharedDirector()->getOpenGLView())@H_301_47@
- CCEGLView*view=CCEGLView::sharedOpenGLView();@H_301_47@
- view->setFrameSize(w,h);@H_301_47@
- CCLog("with%d,height%d",w,h);@H_301_47@
- AppDelegate*pAppDelegate=newAppDelegate();@H_301_47@
- CCApplication::sharedApplication()->run();@H_301_47@
- else@H_301_47@
- ccDrawInit();@H_301_47@
- ccGLInvalidateStateCache();@H_301_47@
- CCShaderCache::sharedShaderCache()->reloadDefaultShaders();@H_301_47@
- CCTextureCache::reloadAllTextures();@H_301_47@
- CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND,NULL);@H_301_47@
- CCDirector::sharedDirector()->setGLDefaultValues();@H_301_47@
- }@H_301_47@
根据Jni的命名规则,那个标注②的nativeInit方法就是上面红色一长串(呵呵)。窗口建立起来后调用nativeInit方法,就是调用这个C++的实现。这里做了窗口的初始化处理。
看标注⑤,你以为这个run函数就进入主循环了么,呵呵
看这个run
<spanstyle="font-size:18px;">//Initializeinstanceandcocos2d.@H_301_47@
- if(!applicationDidFinishLaunching())@H_301_47@
- return0;@H_301_47@
- return-1;@H_301_47@
- }</span>@H_301_47@
我们看到了神马!实质上就调了一下applicationDidFinishLaunching,别的什么也没干。所以这里没有进入主循环。
现在再看③和④。这个逻辑貌似就是主循环。
这个nativeRender()函数的实现在Yourcocos2dDir/cocos2dx/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp
#include"text_input_node/CCIMEDispatcher.h"@H_301_47@
- #include"CCDirector.h"@H_301_47@
- #include"../CCApplication.h"@H_301_47@
- #include"platform/CCFileUtils.h"@H_301_47@
- #include"CCEventType.h"@H_301_47@
- #include"support/CCNotificationCenter.h"@H_301_47@
- #include"JniHelper.h"@H_301_47@
- #include<jni.h>@H_301_47@
- usingnamespacecocos2d;@H_301_47@
- extern"C"{@H_301_47@
- JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_<spanstyle="color:#ff0000;">Cocos2dxRenderer_nativeRender</span>(JNIEnv*env){@H_301_47@
- <spanstyle="color:#ff0000;">cocos2d::CCDirector::sharedDirector()->mainLoop();@H_301_47@
- JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause(){@H_301_47@
- CCApplication::sharedApplication()->applicationDidEnterBackground();@H_301_47@
- CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_BACKGROUND,NULL);@H_301_47@
- JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume(){@H_301_47@
- if(CCDirector::sharedDirector()->getOpenGLView()){@H_301_47@
- CCApplication::sharedApplication()->applicationWillEnterForeground();@H_301_47@
- JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeInsertText(JNIEnv*env,jstringtext){@H_301_47@
- constchar*pszText=env->GetStringUTFChars(text,NULL);@H_301_47@
- cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText,strlen(pszText));@H_301_47@
- env->ReleaseStringUTFChars(text,pszText);@H_301_47@
- JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeDeleteBackward(JNIEnv*env,jobjectthiz){@H_301_47@
- cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();@H_301_47@
- JNIEXPORTjstringJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeGetContentText(){@H_301_47@
- JNIEnv*env=0;@H_301_47@
- if(JniHelper::getJavaVM()->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK||!env){@H_301_47@
- constchar*pszText=cocos2d::CCIMEDispatcher::sharedDispatcher()->getContentText();@H_301_47@
- returnenv->NewStringUTF(pszText);@H_301_47@
- }@H_301_47@
看上面标注,找到导演了,导演又开始主循环了。真是众里寻他千百度,那人却在灯火阑珊处啊。
到这里可以发现,Android上的主循环跟win上的不太一样,它不是一个简单的while就完了。它是由java的渲染线程发起的,通过不断调用render来驱动。
3.iOs
ios上面和Android上类似。看AppController.mm
#import<UIKit/UIKit.h>@H_301_47@
- #import"AppController.h"@H_301_47@
- #import"cocos2d.h"@H_301_47@
- #import"EAGLView.h"@H_301_47@
- #import"AppDelegate.h"@H_301_47@
- #import"RootViewController.h"@H_301_47@
- @implementationAppController@H_301_47@
- @synthesizewindow;@H_301_47@
- @synthesizeviewController;@H_301_47@
- #pragmamark-@H_301_47@
- #pragmamarkApplicationlifecycle@H_301_47@
- //cocos2dapplicationinstance@H_301_47@
- staticAppDelegates_sharedApplication;@H_301_47@
- -(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{@H_301_47@
- //Overridepointforcustomizationafterapplicationlaunch.@H_301_47@
- //Addtheviewcontroller'sviewtothewindowanddisplay.@H_301_47@
- window=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];@H_301_47@
- EAGLView*__glView=[EAGLViewviewWithFrame:[windowbounds]@H_301_47@
- pixelFormat:kEAGLColorFormatRGBA8@H_301_47@
- depthFormat:GL_DEPTH_COMPONENT16@H_301_47@
- preserveBackbuffer:NO@H_301_47@
- sharegroup:nil@H_301_47@
- multiSampling:NO@H_301_47@
- numberOfSamples:0];@H_301_47@
- //UseRootViewControllermanageEAGLView@H_301_47@
- viewController=[[RootViewControlleralloc]initWithNibName:nilbundle:nil];@H_301_47@
- viewController.wantsFullScreenLayout=YES;@H_301_47@
- viewController.view=__glView;@H_301_47@
- //SetRootViewControllertowindow@H_301_47@
- if([[UIDevicecurrentDevice].systemVersionfloatValue]<6.0)@H_301_47@
- //warning:addSubViewdoesn'tworkoniOS6@H_301_47@
- [windowaddSubview:viewController.view];@H_301_47@
- //usethismethodonios6@H_301_47@
- [windowsetRootViewController:viewController];@H_301_47@
- [windowmakeKeyAndVisible];@H_301_47@
- [[UIApplicationsharedApplication]setStatusBarHidden:YES];@H_301_47@
- <spanstyle="color:#ff0000;">cocos2d::CCApplication::sharedApplication()->run();</span>@H_301_47@
- returnYES;@H_301_47@
- -(void)applicationWillResignActive:(UIApplication*)application{@H_301_47@
- Sentwhentheapplicationisabouttomovefromactivetoinactivestate.Thiscanoccurforcertaintypesoftemporaryinterruptions(suchasanincomingphonecallorSMSmessage)orwhentheuserquitstheapplicationanditbeginsthetransitiontothebackgroundstate.@H_301_47@
- UsethismethodtopauSEOngoingtasks,disabletimers,andthrottledownOpenGLESframerates.Gamesshouldusethismethodtopausethegame.@H_301_47@
- cocos2d::CCDirector::sharedDirector()->pause();@H_301_47@
- -(void)applicationDidBecomeActive:(UIApplication*)application{@H_301_47@
- Restartanytasksthatwerepaused(ornotyetstarted)whiletheapplicationwasinactive.IftheapplicationwasprevIoUslyinthebackground,optionallyrefreshtheuserinterface.@H_301_47@
- cocos2d::CCDirector::sharedDirector()->resume();@H_301_47@
- -(void)applicationDidEnterBackground:(UIApplication*)application{@H_301_47@
- Usethismethodtoreleasesharedresources,saveuserdata,invalidatetimers,andstoreenoughapplicationstateinformationtorestoreyourapplicationtoitscurrentstateincaseitisterminatedlater.@H_301_47@
- Ifyourapplicationsupportsbackgroundexecution,calledinsteadofapplicationWillTerminate:whentheuserquits.@H_301_47@
- cocos2d::CCApplication::sharedApplication()->applicationDidEnterBackground();@H_301_47@
- -(void)applicationWillEnterForeground:(UIApplication*)application{@H_301_47@
- Calledaspartoftransitionfromthebackgroundtotheinactivestate:hereyoucanundomanyofthechangesmadeonenteringthebackground.@H_301_47@
- cocos2d::CCApplication::sharedApplication()->applicationWillEnterForeground();@H_301_47@
- -(void)applicationWillTerminate:(UIApplication*)application{@H_301_47@
- Calledwhentheapplicationisabouttoterminate.@H_301_47@
- SeealsoapplicationDidEnterBackground:.@H_301_47@
- #pragmamark-@H_301_47@
- #pragmamarkMemorymanagement@H_301_47@
- -(void)applicationDidReceiveMemoryWarning:(UIApplication*)application{@H_301_47@
- Freeupasmuchmemoryaspossiblebypurgingcacheddataobjectsthatcanberecreated(orreloadedfromdisk)later.@H_301_47@
- cocos2d::CCDirector::sharedDirector()->purgeCachedData();@H_301_47@
- -(void)dealloc{@H_301_47@
- [superdealloc];@H_301_47@
- @end@H_301_47@
直接看标注,跟进run()
if(applicationDidFinishLaunching())@H_301_47@
- <spanstyle="color:#ff0000;">[[CCDirectorCallersharedDirectorCaller]startMainLoop]</span>;@H_301_47@
- }</span>@H_301_47@
再跟标注的startMainLoop()
-(void)startMainLoop@H_301_47@
- //CCDirector::setAnimationInterval()iscalled,weshouldinvalidateitfirst@H_301_47@
- [displayLinkinvalidate];@H_301_47@
- displayLink=nil;@H_301_47@
- NSLog(@"runloop!");@H_301_47@
- displayLink=[NSClassFromString(@"CADisplayLink")displayLinkWithTarget:selfselector:@selector(doCaller:)];@H_301_47@
- [displayLinksetFrameInterval:self.interval];@H_301_47@
- [displayLinkaddToRunLoop:[NSRunLoopcurrentRunLoop]forMode:NSDefaultRunLoopMode];@H_301_47@
- }@H_301_47@
好了,看红色标注。这个貌似循环不起来啊,呵呵。
仔细看他加载的这个类CADisplayLink,就是这个东西循环起来的。这其实就是个定时器,默认每秒运行60次,其有个属性可以设置FPS。看后面有个回调函数doCaller,跟进
-(void)doCaller:(id)sender@H_301_47@
- cocos2d::CCDirector::sharedDirector()->mainLoop();
好了,终于又看到导演了。导演很忙,又开始主循环了。
一旦进入主循环,游戏就开始我们自己设计的游戏逻辑。
打字打的睡着了....不打了