刚接了wp8的,又要转接TV版的啦!又是一顿忙活。
一开始接了第三方的android SDK 发现UI线程会被卡死。然后又自己new thread 去跑手柄控制。但是还是会发生cocos2d-x render 上的崩溃。
每次看报告都是崩溃在线程跳转上。最后还是决定用CCkeypadDelegate 的逻辑去实现。
具体实现方式可以参考:http://blog.csdn.net/keshuiyun/article/details/9788533。 感觉博主。
但是还是存在一个小问题。
就是 我这边上下左右无法连续响应。注册OnkeyLongPess 也无法响应。最后采用定时器自己去连续触发的方式。
我的实现方法:
Cocos2dxGLSurfaceView.java 中添加如下函数: //
private void runqueueEvent()
{
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleKeyDown(mCurKeyCode);
}
});
}
//
private void startTimer()
{
if(mTimer ==null)
{
mTimer = new Timer();
}
if (mTimerTask ==null) {
mTimerTask = new TimerTask() {
@Override
public void run() {
//Log.e("TAG","startTimer KeyCode: = "+mCurKeyCode);
runqueueEvent();
}
};
}
if(mTimer !=null && mTimerTask !=null )
mTimer.schedule(mTimerTask,delay, period);
}
private void stopTimer(){
if (mTimer !=null) {
mTimer.cancel();
mTimer = null;
}
if (mTimerTask !=null) {
mTimerTask.cancel();
mTimerTask = null;
}
}
@Override
public boolean onKeyUp(finalint pKeyCode, final KeyEvent pKeyEvent)
{
Log.e("TAG","onKeyUp KeyCode: = "+pKeyCode);
if(pKeyCode == KeyEvent.KEYCODE_DPAD_LEFT || pKeyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
stopTimer();
}
return super.onKeyUp(pKeyCode, pKeyEvent);
}
public boolean onKeyDown(final int pKeyCode, final KeyEvent pKeyEvent) {
int nRepeatCount = pKeyEvent.getRepeatCount();
long tempLastClickTime = System.currentTimeMillis();
if ((tempLastClickTime -mLastClickTime) < CD_TIME)
{
returntrue;
}
mLastClickTime = tempLastClickTime;
Log.e("TAG","onKeyDown KeyCode: = "+pKeyCode);
//Log.e("TAG","onKeyDown nRepeatCount: = "+nRepeatCount);
switch (pKeyCode) {
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
caseKeyEvent.KEYCODE_BUTTON_A:
caseKeyEvent.KEYCODE_BUTTON_1:
caseKeyEvent.KEYCODE_BUTTON_B:
caseKeyEvent.KEYCODE_BUTTON_2:
caseKeyEvent.KEYCODE_BUTTON_X:
caseKeyEvent.KEYCODE_BUTTON_4:
caseKeyEvent.KEYCODE_BUTTON_Y:
caseKeyEvent.KEYCODE_BUTTON_3:
caseKeyEvent.KEYCODE_DPAD_CENTER:
caseKeyEvent.KEYCODE_DPAD_UP:
caseKeyEvent.KEYCODE_DPAD_DOWN:
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleKeyDown(pKeyCode);
}
});
returntrue;
caseKeyEvent.KEYCODE_DPAD_LEFT:
caseKeyEvent.KEYCODE_DPAD_RIGHT:
if (nRepeatCount == 0){//左右连续按钮
mCurKeyCode = pKeyCode;
startTimer();
}
else
{
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleKeyDown(pKeyCode);
}
});
}
returntrue;
default:
return super.onKeyDown(pKeyCode, pKeyEvent);
}
} ///
#define KEYCODE_BACK 0x04
#define KEYCODE_MENU 0x52
#define KEYCODE_DPAD_UP 19
#define KEYCODE_DPAD_DOWN 20
#define KEYCODE_DPAD_LEFT 21
#define KEYCODE_DPAD_RIGHT 22
#define KEYCODE_DPAD_CENTER 23
#define KEYCODE_BUTTON_A 96
#define KEYCODE_BUTTON_B 97
#define KEYCODE_BUTTON_X 99
#define KEYCODE_BUTTON_Y 100
#define KEYCODE_BUTTON_1 188
#define KEYCODE_BUTTON_2 189
#define KEYCODE_BUTTON_3 190
#define KEYCODE_BUTTON_4 191
../cocos2d-x-2.2.4/cocos2dx/platform/android/jni/TouchesJni.cpp 中修改 Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeKeyDown函数
CCDirector* pDirector = CCDirector::sharedDirector();
switch (keyCode) {
case KEYCODE_BACK:
if (pDirector->getKeypadDispatcher()->dispatchKeypadMSG(kTypeBackClicked))
return JNI_TRUE;
break;
case KEYCODE_MENU:
...依次添加就好。
}
.../cocos2d-x-2.2.4/cocos2dx/keypad_dispatcher/CCKeypadDelegate.h 添加一个响应按键的虚函数:
class CC_DLL CCKeypadDelegate
{
public:
// The back key clicked
virtual void keyBackClicked() {}
// The menu key clicked. only available on wophone & android
virtual void keyMenuClicked() {};
// The menu key clicked. only available on wophone & android
virtual void keyArrowClicked(int nKeyCode) {};
};
../cocos2d-x-2.2.4/cocos2dx/keypad_dispatcher/CCKeypadDispatcher.cpp 添加响应就可以了
bool CCKeypadDispatcher::dispatchKeypadMSG(ccKeypadMSGType nMsgType)
{
CCKeypadHandler* pHandler = NULL;
CCKeypadDelegate* pDelegate = NULL;
m_bLocked = true;
if (m_pDelegates->count() > 0)
{
CCObject* pObj = NULL;
CCARRAY_FOREACH(m_pDelegates, pObj)
{
CC_BREAK_IF(!pObj);
pHandler = (CCKeypadHandler*)pObj;
pDelegate = pHandler->getDelegate();
switch (nMsgType)
{
case kTypeBackClicked:
pDelegate->keyBackClicked();
break;
case kTypeMenuClicked:
pDelegate->keyMenuClicked();
break;
case kTypeButton_A_Clicked:
case kTypeButton_B_Clicked:
case kTypeButton_X_Clicked:
case kTypeButton_Y_Clicked:
case kTypeUpArrowClicked:
case kTypeDownArrowClicked:
case kTypeLeftArrowClicked:
case kTypeRightArrowClicked:
case kTypeEnterClicked:
pDelegate->keyArrowClicked(nMsgType);
break;
default:
break;
}
}
}
...剩余部分省略。
}
//还忘记了CCKeypadDispatcher.h 添加枚举按键类型
/**
* @addtogroup input
* @{
*/
typedef enum {
// the back key clicked msg
kTypeBackClicked = 1,
kTypeMenuClicked,
kTypeButton_A_Clicked,
kTypeButton_B_Clicked,
kTypeButton_X_Clicked,
kTypeButton_Y_Clicked,
kTypeUpArrowClicked,
kTypeDownArrowClicked,
kTypeLeftArrowClicked,
kTypeRightArrowClicked,
kTypeEnterClicked,
} ccKeypadMSGType;
///
CClayer.cpp 添加。
void CCLayer::keyArrowClicked(int nKeyCode)
{
if (m_pScriptKeypadHandlerEntry)
{
CCScriptEngineManager::sharedManager()->getScriptEngine()->executeLayerKeypadEvent(this, nKeyCode);
}
}
// 这样就实现了
class IntroLayer : public CCLayer...
{
public:
....
virtual void keyArrowClicked(int nKeyCode);
...
}
///
我用cocos2d-x 版本是2.2.4的测试可以满足TV版的按钮响应需求。