How to Check for Constant KeyPress in Cocos2d-X? (C++)

88 Views Asked by At

I have been trying to code/develop a function in cocosd2x-x that does a specified action (in my case move the player sprite) , while a key is being pressed; Since Cocos2d-x does not have a specific option in mind (only OnKeyPressed & OnKeyReleased.

I tried to tackle this issue was through utilizing Coco2d's SchedueledUpdate() which updates every frame using delta time.

After defining the function in Level1Scene.h: void UpdateMove(float dt);

I called on it in Level1Scene.cpp and tried to associate it to the player sprite which is called Knight:

void Level1::UpdateMove(float dt) {

    if (::DirX == -1) {
        Director::getInstance()->getRunningScene()->getChildByName("Knight")->setPosition(-10, 0);
    }

    if (::DirX == -1) {
        Director::getInstance()->getRunningScene()->getChildByName("Knight")->setPosition(+10, 0);
    }

    if (::DirY == -1) {
        Director::getInstance()->getRunningScene()->getChildByName("Knight")->setPosition(0, -10);
    }

    if (::DirY == 1) {
        Director::getInstance()->getRunningScene()->getChildByName("Knight")->setPosition(0, +10);
    }
}

As you can see, DirX and DirY are both global int variables that get their values called, which then instructs the game to GetInstance->GetRunningScene()->GetChildByName("Knight"), this Player Sprite then gets its position decreased or increased depending on the button input set in a different function in bool Level1::init() :

auto eventListener = EventListenerKeyboard::create();

    eventListener->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event) {

        switch (keyCode) {
        case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
        case EventKeyboard::KeyCode::KEY_A:
            ::DirX = -1;
            break;
        case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
        case EventKeyboard::KeyCode::KEY_D:
            ::DirX = 1;
            break;
        case EventKeyboard::KeyCode::KEY_UP_ARROW:
        case EventKeyboard::KeyCode::KEY_W:

            ::DirY = -1;
            break;
        case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
        case EventKeyboard::KeyCode::KEY_S:
            ::DirY = +1;
            break;
        }
    };

    this->scheduleUpdate();

Why doesn't this work?

1

There are 1 best solutions below

0
Abderahemane Nejjam On

Updating this in case somebody else stumbles on this in the future with a solution:

After doing a lot of A/B Testing I discovered that the main issue came from the update function not recognizing what sprite I was referring to. After doing some digging, I also unraveled that my main issue lied within:

Director::getInstance()->getRunningScene()->getChildByName("Knight")

This function is apparently buggy and does not fetch the current scene along with the specified child (despite using ->setName("Knight").

To get around this, I declared three global variables outside of the functions:

int DirX = 0 ;
int DirY = 0 ;
cocos2d::Sprite* Knight;

Afterwards, I called on the global knight variable within the init function:

::Knight= Sprite::create("Knight.png");
::Knight->setPosition(Vec2(200, 115));
::Knight->setScale(0.3);
this->addChild(Knight);

as well as DirX and DirY within a keyboard listener event:

keyboardListener->onKeyPressed = [=](EventKeyboard::KeyCode keyCode, Event* event)
{
    switch (keyCode)
    {
    case EventKeyboard::KeyCode::KEY_W:
    case EventKeyboard::KeyCode::KEY_UP_ARROW:
        DirY += 3.0f;
        break;
    case EventKeyboard::KeyCode::KEY_A:
    case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
        DirX -= 3.0f;
        break;
    case EventKeyboard::KeyCode::KEY_S:
    case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
        DirY -= 3.0f;
        break;
    case EventKeyboard::KeyCode::KEY_D:
    case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
        DirX += 3.0f;
        break;
    }
};

keyboardListener->onKeyReleased = [=](EventKeyboard::KeyCode keyCode, Event* event)
{
    switch (keyCode)
    {
    case EventKeyboard::KeyCode::KEY_W:
    case EventKeyboard::KeyCode::KEY_UP_ARROW:
        DirY -= 3.0f;
        break;
    case EventKeyboard::KeyCode::KEY_A:
    case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
        DirX += 3.0f;
        break;
    case EventKeyboard::KeyCode::KEY_S:
    case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
        DirY += 3.0f;
        break;
    case EventKeyboard::KeyCode::KEY_D:
    case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
        DirX -= 3.0f;
        break;
    }
};

this->_eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);

this->scheduleUpdate();

Do note that I've used both onKeyPressed and onKeyReleased with counter values, to fix any movement-related issues.

Finally, in the update function I run a constant check for value that updates the player's position every frame.

void Level1::update(float dt) {

float newPosX = ::Knight->getPositionX() + (DirX);
float newPosY = ::Knight->getPositionY() + (DirY);

::Knight->setPosition(newPosX, newPosY);

}