在使用cocos2dx制作游戏的时候,为了提高android用户的使用,添加了android的按键监听,并且所有的界面联动都监听了bank按键。但是在使用的时候发现,两个layer监听实体键之后都收到了实体键返回。cocos并没有对实体键的反馈做事件消耗。好吧,引擎不做的只好自己实现了。
感谢大神c++实现方案
cocos2dx-3.0+的按键事件处理还是不尽如人意–cocoachina
本文主要是实现lua层和对大神方案的补充,如果有错误还请各位路过大神指点指点,本人将不胜感激
按大神指导修改文件
bool init(Type t, const ListenerID& listenerID, const std::function<bool(Event*)>& callback);//修改
std::function<bool(Event*)> _onEvent; //修改
bool EventListener::init(Type t, const ListenerID& listenerID, const std::function<bool(Event*)>& callback)//修改
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);
}
std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased;//修改
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
virtual bool onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event) { return false; }; //修改
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();//修改位置
}
virtual bool onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event);//修改
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;//修改位置
}
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 >= 1
tolua_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 >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'tolua_cocos2dx_EventListenerKeyboard_registerScriptHandler'.",&tolua_err);
return 0;
#endif
}
代码修改完成,快去试试效果吧!