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?
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:
Afterwards, I called on the global knight variable within the init function:
as well as DirX and DirY within a keyboard listener event:
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) {
}