Fluxo de processamento do mecanismo de jogo Cocos2d-x MainLoop loop principal (abaixo)

Os jogos na plataforma Android começam com uma atividade. (Em outras palavras, parece que todos os aplicativos Android começam na Activity).

Existe um diretório no código-fonte do mecanismo, que é o código java do android, que é um código de modelo. Quase todos os jogos usam isso e não muda muito. Você pode assistir se não acredita em mim

O diretório YourCocos2dxDir/cocos2dx/platform/android/java é onde você copiará o código java como modelo ao criar um projeto android.

Vamos dar uma olhada no código do HelloCpp

[java]   ver  cópia simples

  1. pacote  org.cocos2dx.hellocpp;  
  2.   
  3. import  org.cocos2dx.lib.Cocos2dxActivity;  
  4.   
  5. importar  android.os.Bundle;  
  6.   
  7.  classe pública  HelloCpp  estende  Cocos2dxActivity{  
  8.   
  9.      void protegido  onCreate(Pacote salvadoInstanceState){  
  10.         super .onCreate(savedInstanceState);  
  11.     }  
  12.       
  13.     estático  {  
  14.          System.loadLibrary("hellocpp");  
  15.     }  
  16. }  


Simples, certo. Apenas algumas linhas de código, aqui estão dois problemas

1. Cocos2dxActivity é a Activity principal.

2. A parte C++ do jogo, incluindo a parte do motor, é compilada em uma biblioteca de links dinâmicos hellocpp. Aqui está a biblioteca de links dinâmicos hellocpp carregada.

Essa biblioteca de vínculo dinâmico é gerada ao compilar com o NDK, que é libs/armeabi/libhellocpp.so. (muito longe)

Vamos dar uma olhada na Activity Cocos2dxActivity.

[java]   ver  cópia simples

  1.  classe abstrata  pública  Cocos2dxActivity  estende  Activity  implementa  Cocos2dxHelperListener {  
  2.     // ================================================ =============  
  3.     // Constantes  
  4.     // ================================================ =============  
  5.   
  6.      string final estática  privada  TAG = Cocos2dxActivity. classe .getSimpleName();  
  7.   
  8.     // ================================================ =============  
  9.     // Campos  
  10.     // ================================================ =============  
  11.       
  12.     private  Cocos2dxGLSurfaceView mGLSurfaceView;//Preste atenção a este SurfaceView  
  13.     privado  Cocos2dxHandler mHandler;  
  14.   
  15.     // ================================================ =============  
  16.     // Construtores  
  17.     // ================================================ =============  
  18.   
  19.     @Sobrepor  
  20.      void protegido  onCreate ( Pacote final  saveInstanceState) {  
  21.         super .onCreate(savedInstanceState);  
  22.           
  23.         este .mHandler =  new  Cocos2dxHandler( este );  
  24.   
  25.         este .init();  
  26.   
  27.         Cocos2dxHelper.init( esteeste );  
  28.     }  
  29.   
  30.     // ================================================ =============  
  31.     // Getter & Setter  
  32.     // ================================================ =============  
  33.   
  34.     // ================================================ =============  
  35.     // Métodos para/de SuperClass/Interfaces  
  36.     // ================================================ =============  
  37.   
  38.     @Sobrepor  
  39.      void protegido  onResume() {  
  40.         super .onResume();  
  41.   
  42.         Cocos2dxHelper.onResume();  
  43.         este .mGLSurfaceView.onResume();  
  44.     }  
  45.   
  46.     @Sobrepor  
  47.      void protegido  onPause() {  
  48.         super .onPause();  
  49.   
  50.         Cocos2dxHelper.onPause();  
  51.         este .mGLSurfaceView.onPause();  
  52.     }  
  53.   
  54.     @Sobrepor  
  55.     public  void  showDialog( final  String pTitle,  final  String pMessage) {  
  56.         Mensagem msg =  new  Mensagem();  
  57.         msg.what = Cocos2dxHandler.HANDLER_SHOW_DIALOG;  
  58.         msg.obj =  new  Cocos2dxHandler.DialogMessage(pTitle, pMessage);  
  59.         este .mHandler.sendMessage(msg);  
  60.     }  
  61.   
  62.     @Sobrepor  
  63.     public  void  showEditTextDialog( final  String pTitle,  final  String pContent,  final  int  pInputMode,  final  int  pInputFlag,  final  int  pReturnType,  final  int  pMaxLength) {   
  64.         Mensagem msg =  new  Mensagem();  
  65.         msg.what = Cocos2dxHandler.HANDLER_SHOW_EDITBOX_DIALOG;  
  66.         msg.obj =  new  Cocos2dxHandler.EditBoxMessage(pTitle, pContent, pInputMode, pInputFlag, pReturnType, pMaxLength);  
  67.         este .mHandler.sendMessage(msg);  
  68.     }  
  69.       
  70.     @Sobrepor  
  71.     public  void  runOnGLThread( final  Runnable pRunnable) {  
  72.         este .mGLSurfaceView.queueEvent(pRunnable);  
  73.     }  
  74.   
  75.     // ================================================ =============  
  76.     // Métodos  
  77.     // ================================================ =============  
  78.     public  void  init() {  
  79.           
  80.         // FrameLayout  
  81.         ViewGroup.LayoutParams framelayout_params =  
  82.             novo  ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,  
  83.                                        ViewGroup.LayoutParams.FILL_PARENT);  
  84.         FrameLayout framelayout =  new  FrameLayout( this ); // layout do quadro, que pode ser coberto camada por camada  
  85.         framelayout.setLayoutParams(framelayout_params);  
  86.   
  87.         // Cocos2dxEditText layout  
  88.         ViewGroup.LayoutParams edittext_layout_params =  
  89.             novo  ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,  
  90.                                        ViewGroup.LayoutParams.WRAP_CONTENT);  
  91.         Cocos2dxEditText edittext =  new  Cocos2dxEditText( this );  
  92.         edittext.setLayoutParams(edittext_layout_params);  
  93.   
  94.         // ...adicionar ao FrameLayout  
  95.         framelayout.addView(edittext);  
  96.   
  97.         // Cocos2dxGLSurfaceView  
  98.         este .mGLSurfaceView =  este .onCreateView();  
  99.   
  100.         // ...adicionar ao FrameLayout  
  101.         framelayout.addView( this .mGLSurfaceView);// 添加GLSurfaceView  
  102.   
  103.         this .mGLSurfaceView.setCocos2dxRenderer( new  Cocos2dxRenderer());//Esta linha, um renderizador  
  104.         este .mGLSurfaceView.setCocos2dxEditText(edittext);  
  105.   
  106.         // Definir framelayout como visualização de conteúdo  
  107.         setContentView(framelayout);  
  108.     }  
  109.       
  110.     public  Cocos2dxGLSurfaceView onCreateView() {  
  111.         return  new  Cocos2dxGLSurfaceView( this );  
  112.     }  
  113.   
  114.     // ================================================ =============  
  115.     // Classes internas e anônimas  
  116.     // ================================================ =============  
  117. }  


Um monte de código, hein, hein. Na verdade, o núcleo é o mGLSurfaceView e seu novo renderizador Cocos2dxRenderer(). No Android, a renderização OpenGL é composta por um GLSurfaceView e seu renderizador Render. GLSurfaceView exibe a interface e Render renderiza e atualiza. Este Render é, na verdade, um thread de renderização que é executado continuamente e é mantido pela camada de estrutura. Não há muito a dizer aqui.

Olhe para este Cocos2dxRenderer

[java]   ver  cópia simples

  1. pacote  org.cocos2dx.lib;  
  2.   
  3. import  javax.microedition.khronos.egl.EGLConfig;  
  4. import  javax.microedition.khronos.opengles.GL10;  
  5.   
  6. importar  android.opengl.GLSurfaceView;  
  7.   
  8. public  class  Cocos2dxRenderer  implementa  GLSurfaceView.Renderer {  
  9.     // ================================================ =============  
  10.     // Constantes  
  11.     // ================================================ =============  
  12.   
  13.     privado  final  estático  longo  NANOSECONDSPERSECOND = 1000000000L;  
  14.     privado  final  estático  longo  NANOSECONDSPERMICROSECOND = 1000000;  
  15.   
  16.     private  static  long  sAnimationInterval = ( long ) (1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND);  
  17.   
  18.     // ================================================ =============  
  19.     // Campos  
  20.     // ================================================ =============  
  21.   
  22.     privado  longo  mLlastTickInNanoSeconds;  
  23.     private  int  mScreenWidth;  
  24.     private  int  mScreenHeight;  
  25.   
  26.     // ================================================ =============  
  27.     // Construtores  
  28.     // ================================================ =============  
  29.   
  30.     // ================================================ =============  
  31.     // Getter & Setter  
  32.     // ================================================ =============  
  33.   
  34.     public  static  void  setAnimationInterval( final  double  pAnimationInterval) {  
  35.         Cocos2dxRenderer.sAnimationInterval = ( long ) (pAnimationInterval * Cocos2dxRenderer.NANOSECONDSPERSECOND);  
  36.     }  
  37.   
  38.     public  void  setScreenWidthAndHeight( final  int  pSurfaceWidth,  final  int  pSurfaceHeight) {  
  39.         este .mScreenWidth = pSurfaceWidth;  
  40.         este .mScreenHeight = pSurfaceHeight;  
  41.     }  
  42.   
  43.     // ================================================ =============  
  44.     // Métodos para/de SuperClass/Interfaces  
  45.     // ================================================ =============  
  46.   
  47.     @Override //①Preste atenção aqui  
  48.     public  void  onSurfaceCreated( final  GL10 pGL10,  final  EGLConfig pEGLConfig) {  
  49.         Cocos2dxRenderer.nativeInit( this .mScreenWidth,  this .mScreenHeight);//② Inicializar a janela  
  50.         este .mLastTickInNanoSeconds = System.nanoTime();  
  51.     }  
  52.   
  53.     @Sobrepor  
  54.     public  void  onSurfaceChanged( final  GL10 pGL10,  final  int  pWidth,  final  int  pHeight) {  
  55.     }  
  56.   
  57.     @Override //③Preste atenção aqui  
  58.     public  void  onDrawFrame( final  GL10 gl) {  
  59.         /* 
  60.          * O algoritmo de controle de FPS não é preciso e irá diminuir o FPS 
  61.          * em alguns dispositivos. Então, comente o código de controle do FPS. 
  62.          */  
  63.           
  64.         /* 
  65.         final long nowInNanoSeconds = System.nanoTime(); 
  66.         intervalo longo final = nowInNanoSeconds - this.mLastTickInNanoSeconds; 
  67.         */  
  68.   
  69.         // deve renderizar um quadro quando onDrawFrame() é chamado ou há um  
  70.         // "fantasma"  
  71.         Cocos2dxRenderer.nativeRender();//④ Preste atenção especial a isso  
  72.         /* 
  73.         // controle de fps 
  74.         if (interval < Cocos2dxRenderer.sAnimationInterval) { 
  75.             tentar { 
  76.                 // porque renderizamos antes, então devemos dormir duas vezes intervalo de tempo 
  77.                 Thread.sleep((Cocos2dxRenderer.sAnimationInterval - intervalo) / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND); 
  78.             } catch (exceção final e) { 
  79.             } 
  80.         } 
  81.         this.mLastTickInNanoSeconds = nowInNanoSeconds; 
  82.         */  
  83.     }  
  84.   
  85.     // ================================================ =============  
  86.     // Métodos  
  87.     // ================================================ =============  
  88.   
  89.     private  static  nativo  void  nativeTouchesBegin( final  int  pID,  final  float  pX,  final  float  pY);  
  90.     private  static  nativo  void  nativeTouchesEnd( final  int  pID,  final  float  pX,  final  float  pY);  
  91.     private  static  nativo  void  nativeTouchesMove( final  int [] pIDs,  final  float [] pXs,  final  float [] pYs);  
  92.     private  static  nativo  void  nativeTouchesCancel( final  int [] pIDs,  final  float [] pXs,  final  float [] pYs);  
  93.     privado  estático  nativo  booleano  nativeKeyDown( final  int  pKeyCode);  
  94.     privado  estático  nativo  void  nativeRender();  
  95.     private  static  nativo  void  nativeInit( final  int  pWidth,  final  int  pHeight);  
  96.     privado  estático  nativo  void  nativeOnPause();  
  97.     privado  estático  nativo  void  nativeOnResume();  
  98.   
  99.     public  void  handleActionDown( final  int  pID,  final  float  pX,  final  float  pY) {  
  100.         Cocos2dxRenderer.nativeTouchesBegin(pID, pX, pY);  
  101.     }  
  102.   
  103.     public  void  handleActionUp( final  int  pID,  final  float  pX,  final  float  pY) {  
  104.         Cocos2dxRenderer.nativeTouchesEnd(pID, pX, pY);  
  105.     }  
  106.   
  107.     public  void  handleActionCancel( final  int [] pIDs,  final  float [] pXs,  final  float [] pYs) {  
  108.         Cocos2dxRenderer.nativeTouchesCancel(pIDs, pXs, pYs);  
  109.     }  
  110.   
  111.     public  void  handleActionMove( final  int [] pIDs,  final  float [] pXs,  final  float [] pYs) {  
  112.         Cocos2dxRenderer.nativeTouchesMove(pIDs, pXs, pYs);  
  113.     }  
  114.   
  115.     public  void  handleKeyDown( final  int  pKeyCode) {  
  116.         Cocos2dxRenderer.nativeKeyDown(pKeyCode);  
  117.     }  
  118.   
  119.     public  void  handleOnPause() {  
  120.         Cocos2dxRenderer.nativeOnPause();  
  121.     }  
  122.   
  123.     public  void  handleOnResume() {  
  124.         Cocos2dxRenderer.nativeOnResume();  
  125.     }  
  126.   
  127.     private  static  nativo  void  nativeInsertText( final  String pText);  
  128.     privado  estático  nativo  void  nativeDeleteBackward();  
  129.     privado  estático  nativo  String nativeGetContentText();  
  130.   
  131.     public  void  handleInsertText( final  String pText) {  
  132.         Cocos2dxRenderer.nativeInsertText(pText);  
  133.     }  
  134.   
  135.     public  void  handleDeleteBackward() {  
  136.         Cocos2dxRenderer.nativeDeleteBackward();  
  137.     }  
  138.   
  139.     public  String getContentText() {  
  140.         return  Cocos2dxRenderer.nativeGetContentText();  
  141.     }  
  142.   
  143.     // ================================================ =============  
  144.     // Classes internas e anônimas  
  145.     // ================================================ =============  
  146. }  

Existem muitos códigos, que parecem ser muito complicados. Na verdade, o contexto é muito claro, nós só olhamos para o contexto e não consideramos os detalhes. Vamos seguir a videira...

Primeiramente, você deve saber que o renderizador de GLSurfaceView deve implementar a interface GLSurfaceView.Renderer. São os três métodos Override acima.

onSurfaceCreated é chamado quando a janela é criada e onSurfaceChanged é chamado quando a janela é criada e o tamanho muda. O método onDrawFrame é o mesmo que o método Ondraw da View comum. Depois que a janela é criada e inicializada, o thread de renderização mantém chamando este método. Estes são determinados pela estrutura, é assim que parece. Vamos analisar alguns lugares marcados no código:

Veja a marca ①, a janela está estabelecida e precisa ser inicializada neste momento. Neste momento, ele chama uma função nativa, marcada com ②. Vendo este formulário de função, você pode pensar em alguma coisa, e falarei sobre isso mais tarde.

Observe a marca ③, como mencionado anteriormente, esta função será chamada continuamente pelo thread de renderização (como o loop infinito do loop principal). Então há uma função muito incrível nele ④.

Essa é outra função nativa, hein, hein.

O código nativo é incrível, é C++. Se você conhece, você sabe, mas se você não sabe, pesquise no Google.

Como é java chamando C++, é jni chamando.

Vamos dar uma olhada em main.cpp em jni/hellocpp/

[cpp]   ver  cópia simples

  1. #include "AppDelegate.h"  
  2. #include "plataforma/android/jni/JniHelper.h"  
  3. #include <jni.h>  
  4. #include <android/log.h>  
  5.   
  6. #include "HelloWorldScene.h"  
  7.   
  8. #define LOG_TAG "principal"  
  9. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)  
  10.   
  11. usando  namespace  cocos2d;  
  12.   
  13. externo  "C"  
  14. {  
  15.   
  16. jint JNI_OnLoad(JavaVM *vm,  void  *reservado)  
  17. {  
  18.     JniHelper::setJavaVM(vm);  
  19.   
  20.     retornar  JNI_VERSION_1_4;  
  21. }  
  22.   
  23. void  java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject this, jint w, jint h);  
  24. {  
  25.     if  (!CCDirector::sharedDirector()->getOpenGLView())  
  26.     {  
  27.         CCEGLView *view = CCEGLView::sharedOpenGLView();  
  28.         view->setFrameSize(w, h);  
  29.         CCLog("com %d,altura %d",w,h);  
  30.   
  31.         AppDelegate *pAppDelegate =  new  AppDelegate();  
  32.         CCApplication::sharedApplication()->run(); // Veja aqui⑤  
  33.     }  
  34.     outro  
  35.     {  
  36.         ccDrawInit();  
  37.         ccGLInvalidateStateCache();  
  38.           
  39.         CCShaderCache::sharedShaderCache()->reloadDefaultShaders();  
  40.         CCTextureCache::reloadAllTextures();  
  41.         CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL);  
  42.         CCDirector::sharedDirector()->setGLDefaultValues();   
  43.     }  
  44. }  
  45.   
  46. }  


De acordo com as regras de nomenclatura do Jni, o método nativeInit marcado com ② é a longa string vermelha acima (hehe). Depois que a janela é estabelecida, chamar o método nativeInit é chamar a implementação desse C++. É aqui que a inicialização da janela é feita.

Olhe para a marca ⑤, você acha que essa função de execução entrou no loop principal, hein?

assistir esta corrida

[cpp]   ver  cópia simples

  1. <span style="font-size:18px;"> int  CCApplication::run()  
  2. {  
  3.     // Inicializa a instância e cocos2d.  
  4.     if  (! applicationDidFinishLaunching())  
  5.     {  
  6.         retorna  0;  
  7.     }  
  8.       
  9.     retornar  -1;  
  10. }</span>  


Nós vimos um cavalo! Em essência, applicationDidFinishLaunching foi ajustado e nada mais foi feito. Portanto, o loop principal não é inserido aqui.

Agora olhe para ③ e ④ novamente. Essa lógica parece ser o loop principal.

A implementação desta função nativeRender() está em Yourcocos2dDir/cocos2dx/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp

[cpp]   ver  cópia simples

  1. #include "text_input_node/CCIMEDispatcher.h"  
  2. #include "CCDirector.h"  
  3. #include "../CCApplication.h"  
  4. #include "plataforma/CCFileUtils.h"  
  5. #include "CCEventType.h"  
  6. #include "support/CCNotificationCenter.h"  
  7. #include "JniHelper.h"  
  8. #include <jni.h>  
  9.   
  10. usando  namespace  cocos2d;  
  11.   
  12. externo  "C" {  
  13.     JNIEXPORT  void  JNICALL Java_org_cocos2dx_lib_<span style="color:#ff0000;">Cocos2dxRenderer_nativeRender</span>(JNIEnv* env) {  
  14.         <span style="color:#ff0000;">cocos2d::CCDirector::sharedDirector()->mainLoop();//não vejo nada, o que é isso</span>  
  15.     }  
  16.   
  17.     JNIEXPORT  void  JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause() {  
  18.         CCApplication::sharedApplication()->applicationDidEnterBackground();  
  19.   
  20.         CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_BACKGROUND, NULL);  
  21.     }  
  22.   
  23.     JNIEXPORT  void  JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume() {  
  24.         if  (CCDirector::sharedDirector()->getOpenGLView()) {  
  25.             CCApplication::sharedApplication()->applicationWillEnterForeground();  
  26.         }  
  27.     }  
  28.   
  29.     JNIEXPORT  void  JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInsertText(JNIEnv* env, jobject thiz, jstring text) {  
  30.         const  char * pszText = env->GetStringUTFChars(texto, NULL);  
  31.         cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText));  
  32.         env->ReleaseStringUTFChars(texto, pszText);  
  33.     }  
  34.   
  35.     JNIEXPORT  void  JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeDeleteBackward(JNIEnv* env, jobject thiz) {  
  36.         cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();  
  37.     }  
  38.   
  39.     JNIEXPORT jstring JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeGetContentText() {  
  40.         JNIEnv * env = 0;  
  41.   
  42.         if  (JniHelper::getJavaVM()->GetEnv(( void **)&env, JNI_VERSION_1_4) != JNI_OK || ! env) {  
  43.             retorna  0;  
  44.         }  
  45.         const  char  * pszText = cocos2d::CCIMEDispatcher::sharedDispatcher()->getContentText();  
  46.         return  env->NewStringUTF(pszText);  
  47.     }  
  48. }  


Veja a anotação acima, encontrei o diretor e o diretor iniciou o loop principal novamente. É verdade que a multidão o procurou milhares de vezes, mas o homem estava em um local pouco iluminado.

Pode-se verificar aqui que o loop principal no Android não é o mesmo que no win, não é um simples tempo e acabou. Ele é iniciado pelo thread de renderização do java e conduzido pela chamada contínua de render.

Acho que você gosta

Origin blog.csdn.net/qq_35624156/article/details/126721184
Recomendado
Clasificación