cocos2d-x中新增TV按鍵響應

你的財神爺發表於2018-08-05

最近有個機頂盒專案,需要用到遙控器的方向鍵在遊戲中控制方向。

如果是一般Android裝置、iOS裝置或Win32平臺,cocos2d-x提供了“CCAccelerometer”類,可用於遊戲控制UI。但由於機頂盒在使用過程中是使用遙控器與玩家互動,而遙控器中缺少GSenser,所以只能暫時使用方向鍵和中鍵。好在機頂盒廠家使用了Android標準的鍵值,方向鍵和中鍵與Andriod DPAD按鍵一一對應。

下面講一下如何修改cocos2d-x,以使我們在遊戲中能感知DPAD按鍵訊息。

一 修改cocos2dx\keypad_dispatcher\CCKeypadDelegate.h

為” CCKeypadDelegate”新增2個虛擬函式,完成後為:

 

[cpp] view plaincopy

  1. class CC_DLL CCKeypadDelegate  
  2. {  
  3. public:  
  4.     // The back key clicked  
  5.     virtual void keyBackClicked() {}  
  6.   
  7.     // The menu key clicked. only available on wophone & android  
  8.     virtual void keyMenuClicked() {};  
  9.   
  10.     // The enter key clicked. only available on win32 & android  
  11.     virtual void keyEnterClicked() {};  
  12.   
  13.     // The arrow key clicked. only available on win32 & android  
  14.     virtual void keyArrowClicked(int arrow) {};  
  15. };  

其中” keyEnterClicked”函式用於響應”Enter”鍵,”keyArrowClicked”函式用於響應方向鍵訊息。

二 cocos2dx\keypad_dispatcher\CCKeypadDispatcher.h

修改列舉 ccKeypadMSGType的定義為:

 

[cpp] view plaincopy

  1. typedef enum {  
  2.     // the back key clicked msg  
  3.     kTypeBackClicked = 1,  
  4.     // the menu key clicked msg  
  5.     kTypeMenuClicked,  
  6.     // the Enter key clicked msg  
  7.     kTypeEnterClicked,  
  8.     // the arrow key clicked msg  
  9.     kTypeLeftArrowClicked,  
  10.     kTypeUpArrowClicked,  
  11.     kTypeRightArrowClicked,  
  12.     kTypeDownArrowClicked,  
  13. } ccKeypadMSGType;  

三 cocos2dx\keypad_dispatcher\CCKeypadDispatcher.cpp
修改” dispatchKeypadMSG”函式,在:

 

[cpp] view plaincopy

  1. case kTypeMenuClicked:  
  2.                 pDelegate->keyMenuClicked();  


後新增:

 

 

[cpp] view plaincopy

  1. case kTypeEnterClicked:  
  2.         pDelegate->keyEnterClicked();  
  3.         break;  
  4. case kTypeLeftArrowClicked:  
  5. case kTypeUpArrowClicked:  
  6. case kTypeRightArrowClicked:  
  7. case kTypeDownArrowClicked:  
  8.     pDelegate->keyArrowClicked(nMsgType);  
  9.              break;  


針對Android平臺還需要一下修改:

 

四 cocos2dx\platform\android\java\src\org\cocos2dx\lib\Cocos2dxGLSurfaceView.java
找到” onKeyDown”函式,在其中新增幾個鍵值處理,使函式如下:

 

[java] view plaincopy

  1. @Override  
  2. public boolean onKeyDown(final int pKeyCode, final KeyEvent pKeyEvent) {  
  3.     switch (pKeyCode) {  
  4.         case KeyEvent.KEYCODE_BACK:  
  5.         case KeyEvent.KEYCODE_MENU:  
  6.         case KeyEvent.KEYCODE_DPAD_UP:      // 19  
  7.         case KeyEvent.KEYCODE_DPAD_DOWN:    // 20  
  8.         case KeyEvent.KEYCODE_DPAD_LEFT:    // 21  
  9.         case KeyEvent.KEYCODE_DPAD_RIGHT:   // 22  
  10.         case KeyEvent.KEYCODE_DPAD_CENTER:  // 23  
  11.             this.queueEvent(new Runnable() {  
  12.                 @Override  
  13.                 public void run() {  
  14.                     Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleKeyDown(pKeyCode);  
  15.                 }  
  16.             });  
  17.             return true;  
  18.         default:  
  19.             return super.onKeyDown(pKeyCode, pKeyEvent);  
  20.     }  
  21. }  

*注意:專案目錄中proj.android\src\org\cocos2dx\lib\Cocos2dxGLSurfaceView.java需要修改與此相同。

 

五 cocos2dx\platform\android\jni\TouchesJni.cpp

找到:

 

[cpp] view plaincopy

  1. #define KEYCODE_BACK 0x04  
  2. #define KEYCODE_MENU 0x52  


緊接著在下面新增:

 

 

[cpp] view plaincopy

  1. #define KEYCODE_DPAD_UP     19  
  2.     #define KEYCODE_DPAD_DOWN   20  
  3.     #define KEYCODE_DPAD_LEFT   21  
  4.     #define KEYCODE_DPAD_RIGHT  22  
  5.     #define KEYCODE_DPAD_CENTER 23  

然後修改”Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeKeyDown”函式,如下:

 

 

[cpp] view plaincopy

  1. JNIEXPORT jboolean JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeKeyDown(JNIEnv * env, jobject thiz, jint keyCode) {  
  2.     CCDirector* pDirector = CCDirector::sharedDirector();  
  3.     switch (keyCode) {  
  4.         case KEYCODE_BACK:  
  5.               if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeBackClicked))  
  6.                 return JNI_TRUE;  
  7.             break;  
  8.         case KEYCODE_MENU:  
  9.             if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeMenuClicked))  
  10.                 return JNI_TRUE;  
  11.             break;        
  12.         case KEYCODE_DPAD_UP:  
  13.             if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeUpArrowClicked))  
  14.                 return JNI_TRUE;  
  15.             break;  
  16.         case KEYCODE_DPAD_DOWN:  
  17.             if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeDownArrowClicked))  
  18.                 return JNI_TRUE;  
  19.             break;  
  20.         case KEYCODE_DPAD_LEFT:  
  21.             if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeLeftArrowClicked))  
  22.                 return JNI_TRUE;  
  23.             break;  
  24.         case KEYCODE_DPAD_RIGHT:  
  25.             if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeRightArrowClicked))  
  26.                 return JNI_TRUE;  
  27.             break;       
  28.         case KEYCODE_DPAD_CENTER:  
  29.             if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeEnterClicked))  
  30.                 return JNI_TRUE;  
  31.             break;       
  32.         default:  
  33.             return JNI_FALSE;  
  34.     }  
  35.     return JNI_FALSE;  
  36. }  

至此Android平臺修改完成。
為了方便我們在VS2010中開發,還有針對Win32平臺進行修改:
六 cocos2dx\platform\win32\CCEGLView.cpp

 

找到”WindowProc”函式,找到:

 

[cpp] view plaincopy

  1. if (wParam == VK_F1 || wParam == VK_F2)  
  2.        {  
  3.            CCDirector* pDirector = CCDirector::sharedDirector();  
  4.            if (GetKeyState(VK_LSHIFT) < 0 ||  GetKeyState(VK_RSHIFT) < 0 || GetKeyState(VK_SHIFT) < 0)  
  5.                pDirector->getKeypadDispatcher()->dispatchKeypadMSG(wParam == VK_F1 ? kTypeBackClicked : kTypeMenuClicked);  
  6.        }  
  7.        else if (wParam == VK_ESCAPE)  
  8.        {  
  9.            CCDirector::sharedDirector()->getKeypadDispatcher()->dispatchKeypadMSG(kTypeBackClicked);  
  10.        }  

緊接著在後邊新增:

 

 

[cpp] view plaincopy

  1. else if (wParam == VK_RETURN)  
  2. {  
  3.     CCDirector::sharedDirector()->getKeypadDispatcher()->dispatchKeypadMSG(kTypeEnterClicked);  
  4. }  
  5. else if (wParam >= VK_LEFT && wParam <= VK_DOWN)  
  6. {  
  7.     CCDirector::sharedDirector()->getKeypadDispatcher()->dispatchKeypadMSG((ccKeypadMSGType)(kTypeLeftArrowClicked + wParam - VK_LEFT));  
  8. }  

好,現在Win32平臺也新增完成了,程式中可以響應鍵盤上的方向鍵和Enter鍵。

使用方法如下:
假設我們要在繼承自CCLayer的HelloWorld中相應按鍵,那麼首先在HelloWorld的標頭檔案中新增兩個函式:

 

 

[cpp] view plaincopy

  1. void keyArrowClicked(int arrow);  
  2. void keyEnterClicked();  

然後,在HelloWorld初始化時啟用按鍵功能:

 

 

[cpp] view plaincopy

  1. setKeypadEnabled(true);  

在HelloWorld中實現之前宣告的2個虛擬函式:

 

 

[cpp] view plaincopy

  1. void LLPlaneControlLayer::keyArrowClicked(int arrow)  
  2. {     
  3.     if (arrow == kTypeLeftArrowClicked)  
  4.     {  
  5.         // 左方向鍵按下  
  6.     }  
  7.     else if (arrow == kTypeRightArrowClicked)  
  8.     {  
  9.         // 右方向鍵按下  
  10.     }  
  11.       
  12.     if (arrow == kTypeUpArrowClicked)  
  13.     {  
  14.         // 上方向鍵按下  
  15.     }  
  16.     else if (arrow == kTypeDownArrowClicked)  
  17.     {  
  18.         // 下方向鍵按下  
  19.     }  
  20. }  
  21.   
  22. void LLPlaneControlLayer::keyEnterClicked()  
  23. {  
  24.     // Enter鍵按下  
  25. }  

當使用者按下方向鍵,keyArrowClicked會被執行,引數arrow表示按下的鍵;當使用者按下Enter鍵(Android平臺為DPAD_CENTER鍵),keyEnterClicked函式會執行。

相關文章