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