There was one moment in the default program that still remains unexplained. That’s the button that closed the application.
As you remember the program looked like this:
And after user pressed the button in the bottom left corner the following method was called:
void SmokeTestScene::menuCloseCallback(Ref *pSender) {
// Close the cocos2d-x game scene and quit the application
Director::getInstance()->end();
}
But how does it work? Why the method was called? The whole button gets created like this:
/////////////////////////////
// 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);
Most of this code is similar to construction of a joined node we created in previous post. However, there is one more thing: the CC_CALLBACK_1 macro is used to connect the callback processing method and the menu item.
The CC_CALLBACK_* macros id used very often across Cocos2d programs. It’s implemented with a bit of C++11 magic like this:
// 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__)
The MenuItemImage::create was declared like:
static MenuItemImage * create (const std::string &normalImage, const std::string &selectedImage, const std::string &disabledImage, const ccMenuCallback &callback)
and ccMenuCallback here is a short form for std::function:
typedef std::function<void(Ref*)> ccMenuCallback;
So, the CC_CALBACK_* macro gets two parameters:
The number in CC_CALBACK_* means the number of arguments the callback function will receive.
As a result you’ll get a std::function instance created by std::bind. The Cocos2d-x object will call this instance when the actual event will appear.