Основи Cocos2d-x

Статті про розробку ігор за допомогою Cocos2d-x

Складніша робота з CC_CALLBACK

Posted at — Apr 3, 2020

У попередній статті про колбеки було сказано, що цифра у назві макросу CC_CALLBACK_ задає кількість параметрів, які отримає відповідна функція. Це не зовсім правильно, магія C++ дозволяє зробити з колбеком ще один цікавий фокус.

Візьмемо для прикладу зелене НЛО з цього посту. Переміщення вправо відрізняється від переміщення вліво лише значенням координати, всі інші дії співпадають. Очевидно, було б непогано, якби натиснення на праву та ліву кнопку обробляв один метод, викликаний з різними параметрами. Як цього можна досягти?

Насправді макрос CC_CALLBACK_ може отримувати будь-яку кількість параметрів. Всі ці параметри std::bind передасть у функцію, яка буде викликана.

Краще видно на прикладі. Універсальний колбек для обробки натиснення на кнопку оголошується так:

class ActionsDemoScene : public cocos2d::Scene {
public:
  // .....
protected:
  void ufoMoveCallback(cocos2d::Ref *pSender, const int direction);
};

Тут direction — це той самий параметр, який ми хочемо додати до виклику фунції.

А ось так виглядатиме встановлення колбеку:

MenuItemImage* leftButton = MenuItemImage::create(
    "ui/leftArrow1.png", "ui/leftArrow2.png",
    CC_CALLBACK_1(ActionsDemoScene::ufoMoveCallback, this, GU_MOVE_LEFT));

MenuItemImage* rightButton = MenuItemImage::create(
  "ui/rightArrow1.png", "ui/rightArrow2.png",
  CC_CALLBACK_1(ActionsDemoScene::ufoMoveCallback, this, GU_MOVE_RIGHT));

Тут GU_MOVE_LEFT та GU_MOVE_RIGHT — це константи, які відрізняють два випадки виклику методу.

Відповідно, у реалізації універсального методу може бути щось таке:

void ActionsDemoScene::ufoMoveCallback(Ref *pSender, const int direction) {
  float newX = 0; //undefided at this point
  if (direction == GU_MOVE_RIGHT) {
    newX = rightX;
  }
  else {
    newX = leftX;
  }

  // використання відповідного значення newX
}

В принципі, у даному конкретному прикладі можна було б передавати координату прямо під час створення кнопки, і тоді б if у методі був би зовсім непотрібним. Проте мені така реалізація здалась не дуже наочною, тому я тут використав додатковий параметр direction просто у якості індикатору.