按钮不仅在游戏,在任何地方都是不可或缺却又是最基本的东西。在游戏引擎Cocos2dx中也不例外。
下面用一个例子说明Cocos2dx中如何使用按钮,同时,如果在Cocos2dx中获取层,也就是场景、舞台中的组件。
如下图,有一个按钮Clickme,被点击时候与不被点击的时间,其背景图片是不同的。其实就是资源文件夹Resource中早就被玩坏的两个图片,一张CloseNormal.png一张CloseSelected.png被拉伸后的惨状。
Cocos2dx的资源文件夹在《【Cocos2dx】资源文件夹,播放背景音乐,导入外部库》(点击打开链接)中已经介绍过了。
如何拉伸图片,请参考《【Cocos2dx】使用CCScale9Sprite拉伸图片》(点击打开链接)
在点击的时候,其上方的文字,点击数在改变。点击一次,增加一次。
1、首先还是老样子,利用命令行创建一个工程,这个我就不多说了,可以参考《【Cocos2dx】Windows平台下Cocos2dx 2.x的下载、安装、配置,打造自己的Helloworld》(点击打开链接)
2、之后,打开./projects/工程名/proj.win32/HelloCpp.sln,和《【Cocos2dx】新建场景、场景的切换、设置启动场景与菜单的新建》(点击打开链接)一样,先在AppDelegate.cpp的第22行设置pDirector->setDisplayStats(false);关闭调试相信,直接对Helloworld这个场景进行修改。首先打开HelloWorldScene.h这个文件,原来的Helloworld场景的头文件太过臃肿了,可以删除一些无用的跨平台宏汇编的信息,关键是就是里面的4个函数声明,主要是第3个的函数声明进行参数的扩充,以匹配按钮的点击事件cccontrol_selector,如果不加第2个参数CCControlEvent event是无法通过编译的。
HelloWorldScene.h此文件修改之后的全代码如下:
#include "cocos2d.h" #include "cocos-ext.h"//使用按钮事件,必须要需要的头文件 USING_NS_CC_EXT;//使用按钮事件,必须要需要的命名空间 class HelloWorld : public cocos2d::CCLayer { public: // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::CCScene* scene(); // a selector callback void menuCloseCallback(CCObject* pSender,CCControlEvent event);//对原来的关闭事件进行改造,增加参数,让其支持cccontrol_selector // implement the "static node()" method manually CREATE_FUNC(HelloWorld); };3、之后对HelloWorldScene.cpp这个文件中的bool HelloWorld::init(){}场景初始化布局函数,原本Helloworld场景中,右下角按钮的点击回调函数menuCloseCallback进行修改。修改之后的代码如下,详见注释:
#include "HelloWorldScene.h" #include "cocos-ext.h" //使用按钮事件,必须要需要的头文件 USING_NS_CC; USING_NS_CC_EXT;//使用按钮事件,必须要需要的命名空间 int hits=0;//全局变量,用来统计点击被点击次数 CCScene* HelloWorld::scene() { // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object HelloWorld *layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { //获取屏幕的尺寸、位置信息等 CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); //声明按钮部分 cocos2d::extension::CCScale9Sprite *btn_noraml = cocos2d::extension::CCScale9Sprite::create("CloseSelected.png");//声明CloseNormal图片,用于按钮没被按下时的背景图片 cocos2d::extension::CCScale9Sprite *btn_down = cocos2d::extension::CCScale9Sprite::create("CloseNormal.png");//声明CloseSelected图片,用于按钮被按下时的背景图片 CCLabelTTF *labelTTF = CCLabelTTF::create("Click me!","arial",72);//声明一个文字Click me!第2个参数是字体,仅能使用Resource文件夹中fonts文件夹中的字体,第3个参数是字体大小 CCControlButton *controlButton = CCControlButton::create(labelTTF,btn_noraml);//声明一个按钮,第一个参数是声明的文字、第二个参数是声明的图片 controlButton->setBackgroundSpriteForState(btn_down,CCControlStateHighlighted);//设置按钮被按下时候的背景图片,第一个参数是声明的图片,第二个参数是一个定值常量 controlButton->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));//按钮的中心点位于屏幕的中央 controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::menuCloseCallback), CCControlEventTouchDown);//声明按钮的事件,第三个参数为定值常量意为,点击此按钮之后,触发第二个函数所声明的,下面给出的HelloWorld::menuCloseCallback(){}中所有代码。 this->addChild(controlButton);//将此按钮添加到场景,默认不自动添加 //声明文件部分 CCLabelTTF *label1 = CCLabelTTF::create("0 hits","arial",36);//声明一个文字0 hits! label1->setPosition(ccp(visibleSize.width/2,visibleSize.height-visibleSize.height/6));//按钮的中心点位于屏幕的中央 this->addChild(label1,0,1);//添加此文字到场景中,与普通的this->addChild(label1)不同,第3个参数可以理解为此文件的Tag,也就是类似其他编程语言中id的东西,一会儿,按钮点击触发menuCloseCallback函数的时候,此函数可以通过this->getChildByTag(1);获取这个文字 return true; } //controlButton被点击时候,所触发的事件menuCloseCallback void HelloWorld::menuCloseCallback(CCObject* pSender,CCControlEvent event) { hits++;//点击此数+1 CCLabelTTF *label=(CCLabelTTF*)this->getChildByTag(1);//获取Tag1为1的组件,用label指针指向 label->setString(CCString::createWithFormat("%d hits",hits)->getCString());//将其修改为XXhits,其中createWithFormat的使用同C语言的printf,不赘述 }
(1)menuCloseCallback()与init()通过init()添加组件addChild时候,设置labelTTF的Tag,而menuCloseCallback()通过getChildByTag获取Tag为1的组件,并于安卓的findviewbyid强制类型转换所联系起来,产生互动。
(2)关于众组件在被addChild添加之前,皆要通过setPosition方法设置其位置。其中setPosition中的坐标,必须存活的ccp这个方法中,ccp中不能直接写数字,建议通过Cocos2dx的屏幕百分比来摆放组件。本程序的布局如下图:
Cocos2dx的屏幕坐标是,以屏幕左下角为原点,以屏幕右边为X轴正方向,屏幕上方为Y正方向的坐标轴。其中X轴的取值范围为0到visibleSize.width,Y则为0到visibleSize.height,其中visibleSize需要通过CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();所声明。