[Tutorial] How to get multi-platform keyboard events!

Hello everyone! For a week I’ve been looking on how to make a keyboard work!
I managed to figure it out and I want to share my knowledge with you!
So, before we get started - this tutorial only works on Cocos2d-x 3.0alpha and later.
We will start by making two functions in the scene we want keyboard on.
They will be:

OurScene.h:
void keyPressed(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event);
void keyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event);

OurScene.cpp:
void OurScene::keyPressed(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event)
{

}
void OurScene::keyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event)
{

}

These functions will be called when we press/release a key on the keyboard.
Next we need a listener to look for the keyboard we will create it like so (I did it in the init function)

auto keyboardListener = EventListenerKeyboard::create();
keyboardListener->onKeyPressed = CC_CALLBACK_2(OurScene::keyPressed, this);
keyboardListener->onKeyReleased = CC_CALLBACK_2(OurScene::keyReleased, this);
EventDispatcher::getInstance()->addEventListenerWithSceneGraphPriority(listener, this); // use if your version is below cocos2d-x 3.0alpha.1
// use this: Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this); if you are using cocos2d-x 3.0alpha.1 and later!

This code creates a keyboard listener and then setting what functions will be called when the key is pressed or released.
Now Our program can detect keyboard! Wait… How do I know what key is pressed? It is simple! Let me show you:

//put this inside keyPressed or keyReleased
if (keyCode == EventKeyboard::KeyCode::KEY_W)
{
    CCLog("W key was pressed");
}

This piece of code will check what is the key-code of the key that was pressed. The list of key-codes is inside the EventKeyboard class. To use a keycode you just type:
EventKeyboard::KeyCode::KEY_whatever key - you will usually get a list of available keys to chose from.

Well, I think that’s it! Enjoy!

3 Likes

This is a nice, clean solution. So much better than the hacking required for cocos2d-x 2.x.x.

Thanks a bunch for the tutorial!

Jeremy G wrote:

This is a nice, clean solution. So much better than the hacking required for cocos2d-x 2.x.x.
>
Thanks a bunch for the tutorial!

No problem!
It took me a lot of time to find any solution and the wiki didn’t really explain too much so
when I figured it out I just needed to make a tutorial. :slight_smile:

thanks for the tip!

for anyone else coming across this thread: EventDispatcher::getInstance() no longer exists as of 3.0alpha1. instead, use Director::getInstance()->getEventDispatcher().

bunny hero wrote:

thanks for the tip!
>
for anyone else coming across this thread: EventDispatcher::getInstance() no longer exists as of 3.0alpha1. instead, use Director::getInstance()->getEventDispatcher().

Cool! thanks for updating me! gonna update the tutorial!

This doesn’t seem to work. When I try your code exactly (in a simple cocos2d project created with cocos console, no changes, just default files), nothing happens when I press keys. There seem to be no events created.

Cocos2d version 3.1, testing in Windows 7 64 bit

I tried several approaches and the EventListenerKeyboard stop working when you change the scene, either using Director::getInstance()->pushScene or Director::getInstance()->replaceScene.

I’m using v3.2 stable, and the actual code looks like this:

    OurScene.h:
    void onKeyPressed(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event);
    void onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event);

    OurScene.cpp:
    void OurScene::onKeyPressed(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event)
    {
        CCLOG("Key with keycode %d released", keyCode);
    }
    void OurScene::onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event)
    {
        CCLOG("Key with keycode %d released", keyCode);
    }

   bool OurScene::init()
   {
       auto keyboardListener = cocos2d::EventListenerKeyboard::create();
       keyboardListener->onKeyPressed = CC_CALLBACK_2(OurScene::onKeyPressed, this);
       keyboardListener->onKeyReleased = CC_CALLBACK_2(OurScene::onKeyReleased, this);
    
       _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);
   }

This piece of code works perfectly, since you never shift the scenes. Anyone knows a reason for this misbehavior?

Cheers.

Do any one try it on android platform?
I simply insert following codes in a clean base(at the final of HelloWorld::init()) produced by cocos new:

auto kl = EventListenerKeyboard::create();

kl->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event) {
    CCLOG("%s> keyCode=%d",__FUNCTION__,keyCode);
};
auto ed = Director::getInstance()->getEventDispatcher();
ed->addEventListenerWithSceneGraphPriority(kl,this);

On windows, it worked well. But nothing happened on android.
Log with value of keyCode should be left in logcat, I think.
Do I miss anything?

There seems to be a typo in the code - where you use “listener” as a parameter instead of “keyboardListener”

Hi,
What if i want to continue some action AS LONG as key is pressed?
Any ideas guys?

I may not get your point. If you can see log on logcat when you press key, you can do what ever you want, don’t you?

Think like this , now to move forward in general FPS you dont press and release and press again , you keep on pressing W as long as you want to move. Makes sense?
So basically I want to capture continuous pressing key events?

I can see there are 2 listener events

  1. onKeyPressed
  2. onKeyReleased

I assume the events are work as when a key pressed, if you not release, the onKeyReleased event will not call.

So, you can toggle a state variable in the events
If key pressed and hold, activate move forward state variable, then you will keep move forward (detect the state variable)

If key released after press, deactivate move forward state variable, stop move forward.

Hope this give you some ideas.

I’d like to handle capital letters, too. I’m planning on using onKeyPressed and onKeyReleased to toggle a state if the shift key is pressed or released (same with caps lock). I notice there are keycodes for capital letters, but those aren’t being sent when I type shift-a for example.

The state toggle is working fine.