I have implemented Keyboard event for win platform

I guess I dont have access to sumbit the code.
I will just put changed files here. These files are from version 2.0.3

I hope someone could merge these into repository, as keyboard events are essential for game targeting windows platforms.

Deadkidsong


cocos2dx2.0.2 keyboard implement.rar.zip (29.6 KB)

Looks really good, will integrate in my custom 2.0.4

Thank you! Win32 really needs more support.

Can someone post tutorial, or helloworld example how to use it ?

Thank you very much Deadkidsong!

I “updated” this to version 2.1.3, that is, I copied all the relevant code from Deadkidsong’s files to cocos2dx 2.1.3 files.

I also added support for Lua via CCLayer, so now I can register keyboard handler for a layer in lua code.

I’m not going to write a long tutorial, but main points for making this work for just c*+ code in windows:
# Add keyboard_dispatcher -folder to your libcocos2d project
# Replace CCDirector.h/.cpp and platform/win32/CCEGLView.cpp, also to libcocos2d
# Rest of the files are not needed unless you want to use Lua script!
# Build. Now you can add a new Keyboard Delegate with CCDirector::sharedDirector->getKeyboardDispatcher->addDelegate
# You can have your CCLayer to extend CCKeyboardDelegate for example, or just create new ones. You only have to implement two methods: keyDown and keyUp
#
To be able to add a keyboard handler to CCLayer in lua code:
# Copy and replace the rest of the files
# Now you will need to run build.bat inside tools/tolua**. You might need to extract tolua*+.exe first from the .rar file that should be inside the same folder. You also probably want to run this from command line so you’ll see if any errors happen. If it outputs no text at all, you’re good, I seem to recall.
# Build the project in Visual Studio again, and you’re done. Now the following functions should work for CCLayer in lua code: registerScriptKeyboardHandler(LUA_FUNCTION), unregisterScriptKeyboardHandler(), isKeyboardEnabled(), setKeyboardEnabled(bool)

Example code:

local layer = CCLayer:create()

local function onKeyDown(keyCode)
    print("KEY DOWN: "..tostring(keyCode))
end

local function onKeyUp(keyCode)
    -- do something
end

local function keyboardEventHandler(eventType, keyCode)
    if eventType == "keyDown" then
        onKeyDown(keyCode)
    else
        onKeyUp(keyCode)
    end
end

layer:setKeyboardEnabled(true)
layer:registerScriptKeyboardHandler( keyboardEventHandler )

Here is the minimalist code that I’ve been using for keyboard input on Windows.

#include 
..
//See if the w key is being pressed
if( GetAsyncKeyState(0x57) != 0)
     foo();

I need to thanks first deadkidsong, second sami, 4 days tried to work this, and now work.

just more one example, after follow sami tutorial to build cocos2d-x with keyboard event together

.h file
#include “keyboard_dispatcher\CCKeyboardDispatcher.h”

class GameA : public cocos2d::CCLayer, public cocos2d::CCKeyboardDelegate
{
public:
void keyDown(int keyCode);
void keyUp(int keyCode);
};

.cpp file
“into constructor put this code or init fuction”
CCDirector::sharedDirector()->getKeyboardDispatcher()->addDelegate(this);

“into destructor put this code”
CCDirector::sharedDirector()->getKeyboardDispatcher()->removeDelegate(this);

void GameA::keyUp(int keyCode)
{
CCLOG (“Tecla Up %d”, keyCode);
}

void GameA::keyDown(int keyCode)
{
CCLOG (“Tecla %d”, keyCode);
}

Many thanks again.

thanks a lot Deadkidsong, Sami Peltomaa and Gleidson Siqueira!
but can u explane how to use a multi-key? i mean how can i use 2 keys the same time? for example: i want my player to move and fire the same time, but now it just move or just fire
p.s.: sorry for my eng if i said something wrong…

Issue #1501 was created 8 months ago, but in a low priority.
Cocos2d-x majorly focus on mobile platforms.

@ZheWang,

I quite don’t agree with that, support for Windows, Mac, Linux and Emscripten tends to prove Cocos2D-X is more versatile than only “mobile” platforms.
Plus there is a pull request joint effort to have a clean hardware keyboard support :

It would be a shame to drop it IMHO.

Dmitry F wrote:

but can u explane how to use a multi-key? i mean how can i use 2 keys the same time? for example: i want my player to move and fire the same time, but now it just move or just fire

It’s already working, kinda. You just have to check what the keyCode is in your keyDown/keyUp functions and react to different keyCode in the way you want. For example:

void GameA::keyDown(int keyCode) {
    CCLOG("keyDown: %d", keyCode); // log what key was pressed

    if (keyCode == 32)  // 32 is space
    {
        // call your shoot function
    }
    else if (keyCode == 77)
    {
        // do something else
    }
}

I suspect that might not be your problem anyway, but it’s not clear from your comment :slight_smile:

For holding down keys you have to do something a little bit more complicated. You could store the keyCode to a dictionary on keyDown, and remove it on keyUp. Then you could check in some update function whether the Move-key is in the dictionary (which means it’s held down at the moment) and have your sprite move that frame. Or something, it depends a little bit what kind of game you are making, but for holding down keys just be sure to react only once for a particular key on keyDown, and then wait until keyUp for that key actually happens.

Another possibility would be to not use a dictionary, but just have the keyDown/keyUp events set boolean flags, like player.isShooting = true/false.

Thank you deadkidsong, Sami and Gleidson! This is the closest I’ve managed to get to having keyboard interaction working on windows =D

It seems like keyDown() isn’t working somehow. keyUp() works, but keydown doesn’t seem to ever be called. For instance:

void HelloWorld::keyDown(int keyCode)
{
    exit(1);
    CCSprite* pPlayerSprite = (CCSprite *)this->getChildByTag(10);
    pPlayerSprite->setPositionX(pPlayerSprite->getPositionX() + 10.0);
}

void HelloWorld::keyUp(int keyCode)
{
    CCSprite* pPlayerSprite = (CCSprite *)this->getChildByTag(10);
    pPlayerSprite->setPositionX(pPlayerSprite->getPositionX() + 10.0);
}

Nothing in keyDown ever gets called. Releasing the key causes keyUp to get called however.

I don’t know if anybody has any suggestions, but thanks! =D

Hi,

Do you try comment exit(1)? sounds that exit the code.

Yeah, I put that in there just as a test, to see if keyDown is ever called. The code never exits, which indicates its never even called. If I were to put it in keyUp, however, it would exit, because keyUp is being called correctly…

Sami Peltomaa, i think u didn’t understand what i mean :slight_smile:

1) i hold down first key (first function begins...)
2) then i hold down second key (second function begins AND first function ends, BUT i need first function continued to work)
3) i let second key (second function ends and that's all!!) - this moment i still holding first key, but first function doesn't want to begin again

i think it’s just because keyDown\keyUp take and store only ONE LAST keyCode… and i guess, when i hold down second key, keyUp function calls for first key (i can’t to check it, bcs i haven’t laptop right now), so even if i’ll try to use dictionary or boolean flags, they’ll anyway be reset in keyUp function, when i’ll hold down second key
OR if to assume that keyUp function doesn’t called automaticly, then boolean flags won’t be reset…

and now i have a second problem… it’s time delay BEFORE repeat keyDown function… how can i set it null without changing my windows keyboard options?

Josh J, i use same code to do a game, i guess then you merge the platform folder files something don’t happens, because this files that process the keys calls. You overwrote the files or change only different parts of code?? Try overwrote all files indicate that i guess will work to you.

Good Luck,

@ Dmitry F :

Keydown for second key shouldn’t call keyup for the first key. At least it doesn’t on my machine :stuck_out_tongue: So as long as you make sure only the keyUp stops your first action, it should work. Anyway, I tried to make another example of the sort of approach I mean by modifying HelloCpp. I’m not very good with C++ though (I am mostly working with lua right now) so you can take it with a grain of salt :slight_smile:

In HelloWorldScene.h: [note that I have CCLayer extending CCKeyboardDelegate already, and being added to shared KeyboardDispatcher in it’s init method]
<pre>
class HelloWorld : public cocos2d::CCLayer
{
public:
virtual bool init;
void keyDown override;
void keyUp override;
void update override;
// …
protected:
CCLabelTTF *m_pLabel;
std::unordered_map<int,bool> m_keyMap;
}
</pre>
in HelloWorldScene.cpp:
<pre>
void HelloWorld::keyDown
{
if
{
m_keyMap[keyCode] = true;
CCLog;
}
}
void HelloWorld::keyUp
{
if
{
m_keyMap[keyCode] = false;
CCLog;
}
}
void HelloWorld::update
{
if // left arrow
{
m_pLabel
>setPositionX( m_pLabel~~>getPositionX + dt*10 );
}
if // right arrow
{
m_pLabel~~>setPositionX( m_pLabel~~>getPositionX~~ dt*10 );
}
if (m_keyMap[38]) // up arrow
{
m_pLabel~~>setPositionY + dt*10 );
}
if // down arrow
{
m_pLabel~~>setPositionY( m_pLabel~~>getPositionY~~ dt*10 );
}
}

bool HelloWorld::init()
{
if ( !CCLayer::init() )
{
return false;
}
this~~>setKeyboardEnabled;
this~~>scheduleUpdate();

CCSize visibleSize = CCDirector::sharedDirector()>getVisibleSize;
CCPoint origin = CCDirector::sharedDirector
>getVisibleOrigin;
m_pLabel = CCLabelTTF::create;
m_pLabel~~>setPosition.height));
this~~>addChild(m_pLabel, 1);
// …
}

Even without the stuff that moves the label around, I can see that for each key press I only get one “key pressed” and one “key released” log entry. Even if I press many keys and keep the 1st one down to the end.

why I report this error?
error LNK2019: An undefined external symbol (symbol) was found in function “*declspec public:*thiscall cocos2d::CCKeyboardDelegate::CCKeyboardDelegate(void)” (_imp??0CCKeyboardDelegate@cocos2d@QAEXZ),this symbol was referenced in function “public: __thiscall Box2DLayer::Box2DLayer(void)” (??0Box2DLayer@QAEXZ)