使用Cocos2d-x中的CCMenuItemToggle制作商店
2013-11-12 18:10
423 查看
最近一直在和同学用Cocos2d-x做一款手机游戏,期间做过一个商店的功能,在此写一篇关于使用CCMenuItemToggle来实现商店标签功能。
首先把效果发出来,资源是用的《Banana Kong》的图片,上面的字是自己加的:(W == Weapon,H == Hat, I == Inventory, S == Skill)
达到以下几个效果:
1. 进入商店默认“W标签“是选中状态
2. 点击其他的标签后,前一个标签自动还原
3. 点击一个标签,弹出属于这个标签的元素
刚开始做的时候遇到了很多问题,想过用CCMenuItem,但是CCMenuitem的按下和弹起操作时一次性完成的,并且已经封装,网上有继承CCMenuItem重写的方法,感觉比较复杂。之后想过用CCSprite直接写精灵点击事件,结果也是遇到了一些麻烦,最终用CCMenuItemToggle写了出来,如果大家有什么更好的办法写出这个效果,欢迎拍砖!
然后我们来看创建一个CCMenuItemToggle需要的步骤:
这样就创建了一个开关菜单(Toggle == "开关")。当然最后还要传入CCMenu中。
这里又有几点需要讲的:
1. 从这三句代码可以看到如果要创建CCMenuItemToggle的话首先要创建多个CCMenuItemImage,其实也可以是其他菜单项,我们这里只讲用图片创建。想要看其他创建方式以及想要深入研究的可以看源码,这里不赘述。
2. CCMenuItemToggle::createWithTarget(this, selector, imgNormal, imgSelect, NULL); 从这一句最后的参数NULL可以看出还可以继续添加菜单,创建出多选项开关菜单。同样,我们只需要两个图片。
3. 参数selector是回调函数。
如果我们就这样实现标签效果的话,意味着我们将写四遍上述代码,还要控制他们的位置等等,这样我们就理所当然的想到了将其封装成一个函数。我们定义这样一个函数,用来专门创建开关按钮。
于是我们就可以这样创建标签:
wToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);// HShop是商店类
hToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);
iToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);
sToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);
但是这样依然比较麻烦,这四个标签的位置是有规律的,如果我们将他们使用的图片的文件名改得有规律一点,就可以用一个for循环控制。并且将toggle改为数组形式
于是修改后的代码如下:
1. 这里我把需要的文件都改为Toggle_NormalX.png这种形式的(X代表数字),这样就可以用for循环控制载入相应图片。
2. 使用setSelectedIndex(int n)函数可以把标签设置为需要的状态,n对应的即是函数CCMenuItemToggle* imgToggle = CCMenuItemToggle::createWithTarget(this, selector, imgNormal, imgSelect, NULL);中从第三个参数到之后的各种状态
接下来我们就可以点击各种标签了,并且被点击后的标签不能再被点击(实现选中状态),但是现在呈现的状态确实这样的
这样明显是不对的,应该点击了”I标签“后,”W标签“应该恢复,于是剩下的操作我们就在回调函数toggleIsPressed()中进行操作,先贴代码:
这样,用一个switch语句分别处理这四个标签被按下后的操作,他们的操作都可以总结为:
1. 被点击后不能再进行点击 toggle[XXX]->setEnabled(false);
2. 之前被点击的标签应该复原 toggle[XXX]->setSelectedIndex(0);
其实第二点是可以优化的,我的代码写得非常冗余——点击一个菜单,要复原其他三个菜单。之前我想过用一些方法解决,但是都出了一些莫名其妙的问题,具体我猜是回调函数里这个CCObject * menuItem参数的问题,我使用CCMenuItemToggle* tmp来操作被点击的Toggle总是出问题,如果有哪位大侠解决了的话希望不吝赐教!
这样就实现了我们的标签功能,差不多就这样吧,欢迎拍砖!
首先把效果发出来,资源是用的《Banana Kong》的图片,上面的字是自己加的:(W == Weapon,H == Hat, I == Inventory, S == Skill)
达到以下几个效果:
1. 进入商店默认“W标签“是选中状态
2. 点击其他的标签后,前一个标签自动还原
3. 点击一个标签,弹出属于这个标签的元素
刚开始做的时候遇到了很多问题,想过用CCMenuItem,但是CCMenuitem的按下和弹起操作时一次性完成的,并且已经封装,网上有继承CCMenuItem重写的方法,感觉比较复杂。之后想过用CCSprite直接写精灵点击事件,结果也是遇到了一些麻烦,最终用CCMenuItemToggle写了出来,如果大家有什么更好的办法写出这个效果,欢迎拍砖!
然后我们来看创建一个CCMenuItemToggle需要的步骤:
CCMenuItemImage* toggleNormal = CCMenuItemImage::create("toggleNormal", "toggleSelect"); // 未点击时的图片 CCMenuItemImage* toggleSelect = CCMenuItemImage::create("toggleSelect", "toggleNormal"); // 点击后的图片 CCMenuItemToggle* myToggle = CCMenuItemToggle::createWithTarget(this,selector,toggleNormal,toggleSelect,NULL);// 使用以上两个图片菜单创建一个开关菜单
这样就创建了一个开关菜单(Toggle == "开关")。当然最后还要传入CCMenu中。
这里又有几点需要讲的:
1. 从这三句代码可以看到如果要创建CCMenuItemToggle的话首先要创建多个CCMenuItemImage,其实也可以是其他菜单项,我们这里只讲用图片创建。想要看其他创建方式以及想要深入研究的可以看源码,这里不赘述。
2. CCMenuItemToggle::createWithTarget(this, selector, imgNormal, imgSelect, NULL); 从这一句最后的参数NULL可以看出还可以继续添加菜单,创建出多选项开关菜单。同样,我们只需要两个图片。
3. 参数selector是回调函数。
如果我们就这样实现标签效果的话,意味着我们将写四遍上述代码,还要控制他们的位置等等,这样我们就理所当然的想到了将其封装成一个函数。我们定义这样一个函数,用来专门创建开关按钮。
CCMenuItemToggle* HShop::createToggle(SEL_MenuHandler selector, char * fileNameNormal, char * fileNameSelect) { CCMenuItemImage* imgNormal = CCMenuItemImage::create(fileNameNormal, fileNameSelect); CCMenuItemImage* imgSelect = CCMenuItemImage::create(fileNameSelect, fileNameNormal); CCMenuItemToggle* imgToggle = CCMenuItemToggle::createWithTarget(this, selector, imgNormal, imgSelect, NULL); return imgToggle; }
于是我们就可以这样创建标签:
wToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);// HShop是商店类
hToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);
iToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);
sToggle = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect);
但是这样依然比较麻烦,这四个标签的位置是有规律的,如果我们将他们使用的图片的文件名改得有规律一点,就可以用一个for循环控制。并且将toggle改为数组形式
于是修改后的代码如下:
// 创建商店里的标签 for(int i = 0; i < AllToggle; i++) { char fileNameNormal[50]; // 未选中图片的文件名 char fileNameSelect[50]; // 选中图片的文件名 sprintf(fileNameNormal, "Toggle_Normal%d.png", i); sprintf(fileNameSelect, "Toggle_Select%d.png", i); toggle[i] = HShop::createToggle(menu_selector(HShop::toggleIsPressed), fileNameNormal, fileNameSelect); toggle[i]->setTag(i); // 为每个标签设置Tag值 float padding = 4; // 标签之间的间隔 toggle[i]->setPosition(ccp(48 + toggle[0]->getContentSize().width/2, (visibleSize.height/2 + 3 * (padding + toggle[0]->getContentSize().height)/2) - (toggle[0]->getContentSize().height + padding) * i)); // 标签位置,这个大家自己调一下,因为visibleSize是为了适应分辨率专写的 double f = CCDirector::sharedDirector()->getContentScaleFactor(); // 调整一下大小,这个大家看情况 } toggle[weaponToggle]->setSelectedIndex(1); // 我们刚进入的时候武器标签是被选中的 toggle[weaponToggle]->setEnabled(false); // 选中的标签不能再点击 CCMenu *toggleMenu = CCMenu::create(toggle[0], toggle[1], toggle[2], toggle[3], NULL); // 加入到CCMenu对象中 toggleMenu->setAnchorPoint(ccp(0, 0)); toggleMenu->setPosition(ccp(origin.x, origin.y - 1)); this->addChild(toggleMenu, 0);
1. 这里我把需要的文件都改为Toggle_NormalX.png这种形式的(X代表数字),这样就可以用for循环控制载入相应图片。
2. 使用setSelectedIndex(int n)函数可以把标签设置为需要的状态,n对应的即是函数CCMenuItemToggle* imgToggle = CCMenuItemToggle::createWithTarget(this, selector, imgNormal, imgSelect, NULL);中从第三个参数到之后的各种状态
接下来我们就可以点击各种标签了,并且被点击后的标签不能再被点击(实现选中状态),但是现在呈现的状态确实这样的
这样明显是不对的,应该点击了”I标签“后,”W标签“应该恢复,于是剩下的操作我们就在回调函数toggleIsPressed()中进行操作,先贴代码:
void HShop::toggleIsPressed(CCObject * menuItem) { CCMenuItemToggle* tmp = (CCMenuItemToggle*)menuItem; switch(tmp->getTag()) { case weaponToggle: toggle[weaponToggle]->setEnabled(false); toggle[hatToggle]->setSelectedIndex(0); toggle[hatToggle]->setEnabled(true); toggle[inventoryToggle]->setSelectedIndex(0); toggle[inventoryToggle]->setEnabled(true); toggle[skillToggle]->setSelectedIndex(0); toggle[skillToggle]->setEnabled(true); break; case hatToggle: toggle[hatToggle]->setEnabled(false); toggle[weaponToggle]->setSelectedIndex(0); toggle[weaponToggle]->setEnabled(true); toggle[inventoryToggle]->setSelectedIndex(0); toggle[inventoryToggle]->setEnabled(true); toggle[skillToggle]->setSelectedIndex(0); toggle[skillToggle]->setEnabled(true); break; case inventoryToggle: toggle[inventoryToggle]->setEnabled(false); toggle[weaponToggle]->setSelectedIndex(0); toggle[weaponToggle]->setEnabled(true); toggle[hatToggle]->setSelectedIndex(0); toggle[hatToggle]->setEnabled(true); toggle[skillToggle]->setSelectedIndex(0); toggle[skillToggle]->setEnabled(true); mc->createInventoryCard(); CCScrollView* tem= (CCScrollView*)this->getChildByTag(1); tem->setContentOffset(ccp(0, -(containLayer->getContentSize().height - MYSCROLLVIEW_HEIGHT)), true); break; case skillToggle: toggle[skillToggle]->setEnabled(false); toggle[weaponToggle]->setSelectedIndex(0); toggle[weaponToggle]->setEnabled(true); toggle[hatToggle]->setSelectedIndex(0); toggle[hatToggle]->setEnabled(true); toggle[inventoryToggle]->setSelectedIndex(0); toggle[inventoryToggle]->setEnabled(true); break; default: break; } }
这样,用一个switch语句分别处理这四个标签被按下后的操作,他们的操作都可以总结为:
1. 被点击后不能再进行点击 toggle[XXX]->setEnabled(false);
2. 之前被点击的标签应该复原 toggle[XXX]->setSelectedIndex(0);
其实第二点是可以优化的,我的代码写得非常冗余——点击一个菜单,要复原其他三个菜单。之前我想过用一些方法解决,但是都出了一些莫名其妙的问题,具体我猜是回调函数里这个CCObject * menuItem参数的问题,我使用CCMenuItemToggle* tmp来操作被点击的Toggle总是出问题,如果有哪位大侠解决了的话希望不吝赐教!
这样就实现了我们的标签功能,差不多就这样吧,欢迎拍砖!
相关文章推荐
- cocos2D中scheduleOnce的陷阱
- cocos2d-x 屏幕分辨率自动匹配
- cocos2dx2.2版本之后,如何生成项目工程
- cocos2d-x 中的 CCSprite
- cocos2d-html5 简单的动作函数 Action
- cocos2d-x游戏 去掉IOS7上的StatusBar
- 快速搭建 Cocos2d-HTML5 开发调试环境
- cocos2d-x 2.0.4 封装组合框 ComboBox(转)
- cocoStudioAnimationEditor中引用texturePacker的Plist文件的问题
- cocos2d-x CCTableView动态插入删除元素bug修正及动画表现 (转)
- cocos2d-x
- cocos2d-iPhone 基础之一: director、layer、sprite的初级创建
- 搭建cocos2d-html5 环境
- cocos2dx 第二节 hellocpp 源码分析 整体思路
- cocos2dx 第一节 调通的hellocpp源码
- cocos2d-x android 开发环境配置小记
- Cocos2d-x简易手势识别
- cocos2d-x在NDK r9下的编译问题
- 【COCOS2D-X(1.X 2.X) Json(cpp版)及新加字体库篇】在Cocos2dx引擎中封装、解析Json(cpp版)数据以及添加自定义字体库 .
- 【cocos2d-x 手游研发----目录】