cocos2dx lua android按键反馈的消耗机制实现
16lz
2021-01-25
在使用cocos2dx制作游戏的时候,为了提高android用户的使用,添加了android的按键监听,并且所有的界面联动都监听了bank按键。但是在使用的时候发现,两个layer监听实体键之后都收到了实体键返回。cocos并没有对实体键的反馈做事件消耗。好吧,引擎不做的只好自己实现了。
参考网页
感谢大神c++实现方案
cocos2dx-3.0+的按键事件处理还是不尽如人意–cocoachina
本文主要是实现lua层和对大神方案的补充,如果有错误还请各位路过大神指点指点,本人将不胜感激
实现
按大神指导修改文件
- CCEventListener.h
bool init(Type t, const ListenerID& listenerID, const std::function<bool(Event*)>& callback);//修改
std::function<bool(Event*)> _onEvent; //修改
- CCEventListener.cpp
bool EventListener::init(Type t, const ListenerID& listenerID, const std::function<bool(Event*)>& callback)//修改
- CCEventDispatcher.cpp
void EventDispatcher::dispatchEvent(Event* event){ if (!_isEnabled) return; updateDirtyFlagForSceneGraph(); DispatchGuard guard(_inDispatch); if (event->getType() == Event::Type::TOUCH) { dispatchTouchEvent(static_cast(event)); return; } auto listenerID = __getListenerID(event); sortEventListeners(listenerID); auto pfnDispatchEventToListeners = &EventDispatcher::dispatchEventToListeners; if (event->getType() == Event::Type::MOUSE) { pfnDispatchEventToListeners = &EventDispatcher::dispatchTouchEventToListeners; } auto iter = _listenerMap.find(listenerID); if (iter != _listenerMap.end()) { auto listeners = iter->second; auto onEvent = [&event](EventListener* listener) -> bool{ event->setCurrentTarget(listener->getAssociatedNode()); //listener->_onEvent(event);//修改位置 //return event->isStopped(); return listener->_onEvent(event) || event->isStopped(); }; (this->*pfnDispatchEventToListeners)(listeners, onEvent); } updateListeners(event);}
- CCEventListenerKeyboard.h
std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased;//修改
- CCEventListenerKeyboard.cpp
bool EventListenerKeyboard::init(){ auto listener = [this](Event* event)->bool{//修改位置 auto keyboardEvent = static_cast(event); if (keyboardEvent->_isPressed) { if (onKeyPressed != nullptr) onKeyPressed(keyboardEvent->_keyCode, event); } else { if (onKeyReleased != nullptr) return onKeyReleased(keyboardEvent->_keyCode, event);//修改位置 } return false;//修改位置 }; if (EventListener::init(Type::KEYBOARD, LISTENER_ID, listener)) { return true; } return false;}
- CCEventListenerAcceleration.cpp
bool EventListenerAcceleration::init(const std::function<void(Acceleration*, Event* event)>& callback){ auto listener = [this](Event* event)->bool{//修改位置 auto accEvent = static_cast(event); this->onAccelerationEvent(&accEvent->_acc, event); return event->isStopped();//修改位置 }; if (EventListener::init(Type::ACCELERATION, LISTENER_ID, listener)) { onAccelerationEvent = callback; return true; } return false;}
- CCEventListenerController.cpp
bool EventListenerController::init(){ auto listener = [this](Event* event)->bool{//修改位置 auto evtController = static_cast(event); switch (evtController->getControllerEventType()) { case EventController::ControllerEventType::CONNECTION: if (evtController->isConnected()) { if (this->onConnected) this->onConnected(evtController->getController(), event); } else { if (this->onDisconnected) this->onDisconnected(evtController->getController(), event); } break; case EventController::ControllerEventType::BUTTON_STATUS_CHANGED: { const auto& keyStatus = evtController->_controller->_allKeyStatus[evtController->_keyCode]; const auto& keyPrevStatus = evtController->_controller->_allKeyPrevStatus[evtController->_keyCode]; if (this->onKeyDown && keyStatus.isPressed && !keyPrevStatus.isPressed) { this->onKeyDown(evtController->_controller, evtController->_keyCode, event); } else if (this->onKeyUp && !keyStatus.isPressed && keyPrevStatus.isPressed) { this->onKeyUp(evtController->_controller, evtController->_keyCode, event); } else if (this->onKeyRepeat && keyStatus.isPressed && keyPrevStatus.isPressed) { this->onKeyRepeat(evtController->_controller, evtController->_keyCode, event); } } break; case EventController::ControllerEventType::AXIS_STATUS_CHANGED: { if (this->onAxisEvent) { this->onAxisEvent(evtController->_controller, evtController->_keyCode, event); } } break; default: CCASSERT(false, "Invalid EventController type"); break; } return event->isStopped();//修改位置 }; if (EventListener::init(EventListener::Type::GAME_CONTROLLER, LISTENER_ID, listener)) { return true; } return false;}
- CCEventListenerCustom.cpp
bool EventListenerCustom::init(const ListenerID& listenerId, const std::function<void(EventCustom*)>& callback){ bool ret = false; _onCustomEvent = callback; auto listener = [this](Event* event)->bool {//修改位置 if (_onCustomEvent != nullptr) { _onCustomEvent(static_cast(event)); } return event->isStopped();//修改位置 }; if (EventListener::init(EventListener::Type::CUSTOM, listenerId, listener)) { ret = true; } return ret;}
- CCEventListenerFocus.cpp
bool EventListenerFocus::init(){ auto listener = [this](Event* event)->bool{//修改位置 auto focusEvent = static_cast(event); onFocusChanged(focusEvent->_widgetLoseFocus, focusEvent->_widgetGetFocus); return event->isStopped();//修改位置 }; if (EventListener::init(Type::FOCUS, LISTENER_ID, listener)) { return true; } return false;}
- CCEventListenerMouse.cpp
bool EventListenerMouse::init(){ auto listener = [this](Event* event)->bool{//修改位置 auto mouseEvent = static_cast(event); switch (mouseEvent->_mouseEventType) { case EventMouse::MouseEventType::MOUSE_DOWN: if(onMouseDown != nullptr) onMouseDown(mouseEvent); break; case EventMouse::MouseEventType::MOUSE_UP: if(onMouseUp != nullptr) onMouseUp(mouseEvent); break; case EventMouse::MouseEventType::MOUSE_MOVE: if(onMouseMove != nullptr) onMouseMove(mouseEvent); break; case EventMouse::MouseEventType::MOUSE_SCROLL: if(onMouseScroll != nullptr) onMouseScroll(mouseEvent); break; default: break; } return event->isStopped();//修改位置 }; if (EventListener::init(Type::MOUSE, LISTENER_ID, listener)) { return true; } return false;}
- CCInputDelegate.h
virtual bool onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event) { return false; }; //修改
- UIWidget.cpp
bool onKeypadKeyPressed(EventKeyboard::KeyCode, Event*);//修改
bool Widget::FocusNavigationController::onKeypadKeyPressed(EventKeyboard::KeyCode keyCode, Event *event){ if (_enableFocusNavigation && _firstFocusedWidget) { if (keyCode == EventKeyboard::KeyCode::KEY_DPAD_DOWN) { _firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(Widget::FocusDirection::DOWN, _firstFocusedWidget); } if (keyCode == EventKeyboard::KeyCode::KEY_DPAD_UP) { _firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(Widget::FocusDirection::UP, _firstFocusedWidget); } if (keyCode == EventKeyboard::KeyCode::KEY_DPAD_LEFT) { _firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(Widget::FocusDirection::LEFT, _firstFocusedWidget); } if (keyCode == EventKeyboard::KeyCode::KEY_DPAD_RIGHT) { _firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(Widget::FocusDirection::RIGHT, _firstFocusedWidget); } } return event->isStopped();//修改位置}
- CCLayer.h
virtual bool onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event);//修改
- CCLayer.cpp
bool Layer::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* unused_event){ CC_UNUSED_PARAM(unused_event);#if CC_ENABLE_SCRIPT_BINDING if(kScriptTypeNone != _scriptType) { KeypadScriptData data(keyCode, this); ScriptEvent event(kKeypadEvent,&data); return ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);//修改位置 }#endif return false;//修改位置}
- lua_cocos2dx_manual.cpp
static int lua_cocos2dx_Layer_setKeyboardEnabled(lua_State* L){ if (nullptr == L) return 0; int argc = 0; Layer* self = nullptr;#if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; if (!tolua_isusertype(L,1,"cc.Layer",0,&tolua_err)) goto tolua_lerror;#endif self = static_cast(tolua_tousertype(L,1,0));#if COCOS2D_DEBUG >= 1 if (nullptr == self) { tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_Layer_setKeyboardEnabled'\n", NULL); return 0; }#endif argc = lua_gettop(L) - 1; if (1 == argc) {#if COCOS2D_DEBUG >= 1 if (!tolua_isboolean(L, 2, 0, &tolua_err)) goto tolua_lerror;#endif bool enabled = tolua_toboolean(L, 2, 0); auto dict = static_cast<__Dictionary*>(self->getUserObject()); if (dict == nullptr) { dict = __Dictionary::create(); self->setUserObject(dict); } dict->setObject(__Bool::create(enabled), "keyboardEnabled"); auto keyboardListener = static_cast(dict->objectForKey("keyboardListener")); auto dispatcher = self->getEventDispatcher(); dispatcher->removeEventListener(keyboardListener); if (enabled) { auto listener = EventListenerKeyboard::create(); listener->onKeyPressed = [self](EventKeyboard::KeyCode keyCode, Event* event){ }; listener->onKeyReleased = [self](EventKeyboard::KeyCode keyCode, Event* event){ KeypadScriptData data(keyCode, self); ScriptEvent scriptEvent(kKeypadEvent,&data); return ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&scriptEvent);//修改位置 }; CCLOG("come in the keyboardEnable"); dispatcher->addEventListenerWithSceneGraphPriority(listener, self); dict->setObject(listener, "keyboardListener"); } return 0; } luaL_error(L, "%s has wrong number of arguments: %d, was expecting %d\n", "cc.Layer:setKeyboardEnabled", argc, 1); return 0;#if COCOS2D_DEBUG >= 1tolua_lerror: tolua_error(L,"#ferror in function 'lua_cocos2dx_Layer_setKeyboardEnabled'.",&tolua_err); return 0;#endif}
static void cloneKeyboardHandler(const EventListenerKeyboard* src,EventListenerKeyboard* dst, ScriptHandlerMgr::HandlerType type){ if (nullptr == src || nullptr == dst) return; LUA_FUNCTION handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)src, type); if (0 != handler) { int newscriptHandler = cocos2d::ScriptEngineManager::getInstance()->getScriptEngine()->reallocateScriptHandler(handler); ScriptHandlerMgr::getInstance()->addObjectHandler((void*)dst, newscriptHandler, type); switch (type) { case ScriptHandlerMgr::HandlerType::EVENT_KEYBOARD_PRESSED: { dst->onKeyPressed = [=](EventKeyboard::KeyCode keyCode, Event* event){ LuaEventKeyboarData listenerData((int)keyCode, event); BasicScriptData data((void*)dst,(void*)&listenerData); LuaEngine::getInstance()->handleEvent(type, (void*)&data); }; } break; case ScriptHandlerMgr::HandlerType::EVENT_KEYBOARD_RELEASED: { dst->onKeyReleased = [=](EventKeyboard::KeyCode keyCode, Event* event){ LuaEventKeyboarData listenerData((int)keyCode, event); BasicScriptData data((void*)dst,(void*)&listenerData); return LuaEngine::getInstance()->handleEvent(type, (void*)&data);//修改位置 }; } break; default: break; } }}
static int tolua_cocos2dx_EventListenerKeyboard_registerScriptHandler(lua_State* tolua_S){ if (nullptr == tolua_S) return 0; int argc = 0; EventListenerKeyboard* self = nullptr;#if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; if (!tolua_isusertype(tolua_S, 1, "cc.EventListenerKeyboard", 0, &tolua_err)) goto tolua_lerror;#endif self = static_cast(tolua_tousertype(tolua_S,1,0));#if COCOS2D_DEBUG >= 1 if (nullptr == self) { tolua_error(tolua_S,"invalid 'self' in function 'tolua_cocos2dx_EventListenerKeyboard_registerScriptHandler'\n", nullptr); return 0; }#endif argc = lua_gettop(tolua_S) - 1; if (argc == 2) {#if COCOS2D_DEBUG >= 1 if (!toluafix_isfunction(tolua_S,2,"LUA_FUNCTION",0,&tolua_err) || !tolua_isnumber(tolua_S, 3, 0, &tolua_err)) { goto tolua_lerror; }#endif LUA_FUNCTION handler = toluafix_ref_function(tolua_S,2,0); ScriptHandlerMgr::HandlerType type = static_cast((int)tolua_tonumber(tolua_S, 3, 0)); switch (type) { case ScriptHandlerMgr::HandlerType::EVENT_KEYBOARD_PRESSED: { ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); self->onKeyPressed = [=](EventKeyboard::KeyCode keyCode, Event* event){ LuaEventKeyboarData listenerData((int)keyCode, event); BasicScriptData data((void*)self,(void*)&listenerData); LuaEngine::getInstance()->handleEvent(type, (void*)&data); }; } break; case ScriptHandlerMgr::HandlerType::EVENT_KEYBOARD_RELEASED: { ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, type); self->onKeyReleased = [=](EventKeyboard::KeyCode keyCode, Event* event){ LuaEventKeyboarData listenerData((int)keyCode, event); BasicScriptData data((void*)self,(void*)&listenerData); return LuaEngine::getInstance()->handleEvent(type, (void*)&data);//修改位置 }; } break; default: break; } return 0; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n", "cc.EventListenerKeyboard:registerScriptHandler", argc, 2); return 0;#if COCOS2D_DEBUG >= 1tolua_lerror: tolua_error(tolua_S,"#ferror in function 'tolua_cocos2dx_EventListenerKeyboard_registerScriptHandler'.",&tolua_err); return 0;#endif}
代码修改完成,快去试试效果吧!
更多相关文章
- 浅析Android(安卓)App的相对布局RelativeLayout
- 程序媛也话Android(安卓)之 自定义控件(垂直方向滑动条)
- InputFilter实现EditText文本输入过滤器
- Android(安卓)弹无虚发之第五弹:来点儿不一样的Toast(自定义Toast,
- Android招财进宝手势密码的实现
- Android(安卓)Studio 错误: 编码GBK的不可映射字符;gradle projec
- Android:EditText属性大全
- Android(安卓)View 随手指移动
- Programming access to Android(安卓)Market