Основи Cocos2d-x

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

Обробка подій та колбеки

Posted at — Mar 26, 2020

У дефолній програмі, яку було створено у перших постах, залишився без пояснення ще один момент — це кнопка, за допомогою якої ця програма закривалась.

Використання CC_CALLBACK_1 у MenuItemImage

Сама програма, якщо пам'ятаєте, виглядала так:

Тестова програма

Якщо ви мишкою натискали на кнопку в правому нижньому куті, викликався ось такий метод, який припиняв роботу програми:

void SmokeTestScene::menuCloseCallback(Ref *pSender) {
  // Close the cocos2d-x game scene and quit the application
  Director::getInstance()->end();
}

Але чому цей колбек взагалі викликається? Вся кнопка створюється ось таким чином:

/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
//    you may modify it.

// add a "close" icon to exit the progress. it's an autorelease object
auto closeItem = MenuItemImage::create(
  "CloseNormal.png",
  "CloseSelected.png",
  CC_CALLBACK_1(SmokeTestScene::menuCloseCallback, this));

if ((closeItem == nullptr) ||
    (closeItem->getContentSize().width <= 0) ||
    (closeItem->getContentSize().height <= 0)) {
  problemLoading("'CloseNormal.png' and 'CloseSelected.png'");
}
else {
  float x = origin.x + visibleSize.width - closeItem->getContentSize().width / 2;
  float y = origin.y + closeItem->getContentSize().height / 2;
  closeItem->setPosition(Vec2(x, y));
}


// create menu, it's an autorelease object
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);

Більшість цього коду нагадує конструювання складного спрайту, яке ми вже розглядали раніше. Але є один новий момент: використання макросу CC_CALLBACK_1 для того, щоб прив'язати метод, що буде обробляти колбек, до об'єкту меню.

Макроси CC_CALLBACK_* у Cocos2d зустрічаються дуже часто, а реалізовані вони за допомогою магії C++11, приблизно так:

// new callbacks based on C++11
#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)

Функція MenuItemImage::create оголошена таким чином:

static MenuItemImage * 	create (const std::string &normalImage, const std::string &selectedImage, const std::string &disabledImage, const ccMenuCallback &callback)

де ccMenuCallback є просто короткою формою для std::function:

typedef std::function<void(Ref*)> ccMenuCallback;

Таким чином, макрос CC_CALBACK_* отримує два параметри:

Число у макросі CC_CALBACK_* означає кількість аргументів, які отримає функція-колбек.

Результатом є std::function, створений std::bind. Об'єкт Cocos2d, який отримав такий колбек, збереже його і викличе, коли буде потрібно.