cpp-tests Node::Layer及Node::Menu
来源:互联网 发布:淘宝产品怎么排名靠前 编辑:程序博客网 时间:2024/05/17 04:47
~~~~我的生活,我的点点滴滴!!
1、Layer层
Layer 游戏中的背景容器,Layer类是Node类的一个子类,它实现了触屏事件代理(TouchEventsDelegate)协议。
LayerColor是Layer的一个子类,它实现了RGBAProtocol协议。
LayerGradient是LayerColor的一个子类,它在背景上画渐变效果。
LayerMultiplex类是一个能够使它的子类进行复用的布景层类。
Sprite精灵不能直接放入舞台中,它需要作为Layer的子节点,通过Layer加入舞台场景中显示。
cpp-tests例子中Node::Layer测试了很多Layer及其子类的作用与用法,比如递归设置Cascading与opacity来让在Layer层上面的精灵具有及相应的属
性等等,LayerMultiple类在MenuTest里面讲解,下面讲解一下渐变Layer即LayerGradient。
LayerGradient它实现了LayerColor类的所有功能,还添加了以下这些新功能:
1、渐变方向
2、渐变最终颜色
3、插值模式
颜色沿着给定的向量插在起始颜色和终止颜色之间(从起点开始,到终点结束)。如果没有提供向量,则默认到(0,-1)点一个从顶部到底部的淡入
淡出。
如果“compressedInterpolation”不可用,你将看不到非基本向量的起始颜色和终止颜色;不过无论如何,一个平滑的渐变 (包括终点)最终还是会
呈现出来。
如果“compressedInterpolation”是可用的(默认模式),你将看到渐变的起始颜色和终止颜色。
看下面代码:
LayerGradientTest::LayerGradientTest(){//渐变,第一个参数是起始颜色,第二个参数是终止颜色,第三个参数是渐变方向是通过与原点减来求矢量的;//这里(0.9f,0.9f)与(0,0)计算后的夹角是45度往x轴正方向,也就是向右;//如果没有第三个参数,则默认到(0,-1)一个从顶部到底部的淡入淡出; auto layer1 = LayerGradient::create(Color4B(255,0,0,255), Color4B(0,255,0,255), Vec2(0.9f, 0.9f)); addChild(layer1, 0, kTagLayer); auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesMoved = CC_CALLBACK_2(LayerGradientTest::onTouchesMoved, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto label1 = Label::createWithTTF("Compressed Interpolation: Enabled", "fonts/Marker Felt.ttf", 26); auto label2 = Label::createWithTTF("Compressed Interpolation: Disabled", "fonts/Marker Felt.ttf", 26); auto item1 = MenuItemLabel::create(label1); auto item2 = MenuItemLabel::create(label2);//设置一个toggle开关,来演示Compressed,本人目测效果不明显; auto item = MenuItemToggle::createWithCallback( CC_CALLBACK_1(LayerGradientTest::toggleItem, this), item1, item2, nullptr); auto menu = Menu::create(item, nullptr); addChild(menu); auto s = Director::getInstance()->getWinSize(); menu->setPosition(Vec2(s.width / 2, 100));}void LayerGradientTest::toggleItem(Ref *sender){ auto gradient = static_cast<LayerGradient*>( getChildByTag(kTagLayer) ); gradient->setCompressedInterpolation(! gradient->isCompressedInterpolation());}void LayerGradientTest::onTouchesMoved(const std::vector<Touch*>& touches, Event *event){ auto s = Director::getInstance()->getWinSize(); auto touch = touches[0]; auto start = touch->getLocation(); auto diff = Vec2(s.width/2,s.height/2) - start; diff = diff.getNormalized(); auto gradient = static_cast<LayerGradient*>( getChildByTag(1) );//设置一个移动矢量方向 gradient->setVector(diff);}
上面代码会产生一个从左下角红色慢慢变到右上角绿色的Layer层,当鼠标点击移动后,根顺着鼠标移动方向切换渐变颜色位置。
效果图:
2、Menu菜单
菜单按钮有好多了,像MenuItemSprite、MenuItemFont、MenuItemLabel、MenuItemImage、MenuItemToggle等等,都是大同小异,直接看后缀也大概
知道分别代表什么意思,怎么使用了。
下面代码列出了上面的使用方法:
MenuLayerMainMenu::MenuLayerMainMenu(){ _touchListener = EventListenerTouchOneByOne::create(); _touchListener->setSwallowTouches(true); _touchListener->onTouchBegan = CC_CALLBACK_2(MenuLayerMainMenu::onTouchBegan, this); _touchListener->onTouchMoved = CC_CALLBACK_2(MenuLayerMainMenu::onTouchMoved, this); _touchListener->onTouchEnded = CC_CALLBACK_2(MenuLayerMainMenu::onTouchEnded, this); _touchListener->onTouchCancelled = CC_CALLBACK_2(MenuLayerMainMenu::onTouchCancelled, this); //注意这里使用的是FixedPriority而不是SceneGraphPriority;//FixedPriority会依据手动设置的值的顺序来决定触摸的优先级,但是不能为0;//0已经留给scene了 _eventDispatcher->addEventListenerWithFixedPriority(_touchListener, 1); // Font Item // 这里其实是一张图片有三个等分小图片,通过计算其位置来获得图片,plist文件里面其实也是这样的;// 这里的Rect值算的有问题,x,y坐标要缩小一倍,width与height也要缩小一倍;// 要不然显示出来的就是一个空白黄色立方形; auto spriteNormal = Sprite::create(s_MenuItem, Rect(0,23*0.5*2,115*0.5,23*0.5)); auto spriteSelected = Sprite::create(s_MenuItem, Rect(0,23*0.5*1,115*0.5,23*0.5)); auto spriteDisabled = Sprite::create(s_MenuItem, Rect(0,23*0.5*0,115*0.5,23*0.5)); auto item1 = MenuItemSprite::create(spriteNormal, spriteSelected, spriteDisabled , CC_CALLBACK_1(MenuLayerMainMenu::menuCallback, this) ); // Image Item auto item2 = MenuItemImage::create(s_SendScore, s_PressSendScore, CC_CALLBACK_1(MenuLayerMainMenu::menuCallback2, this) ); // Label Item (LabelAtlas) auto labelAtlas = LabelAtlas::create("0123456789", "fonts/labelatlas.png", 16, 24, '.'); auto item3 = MenuItemLabel::create(labelAtlas, CC_CALLBACK_1(MenuLayerMainMenu::menuCallbackDisabled, this) ); /*设置一层覆盖颜色,上一行代码给item3设置了一个触摸回调函数,后面代码;_disabledItem = item3; item3->retain(); _disabledItem->setEnabled( false );把_disabledItem指向item3并且设置setEnabled为false让其不可用状态;这样相当于在item3上面覆盖一层,这样触摸就可控制了;为什么不直接使用item3????;;;;*/item3->setDisabledColor( Color3B(232,0,0) );//设置字体颜色; item3->setColor( Color3B(200,200,255) ); // Font Item auto item4 = MenuItemFont::create("I toggle enable items", [&](Ref *sender) { //设置是否可用;_disabledItem->setEnabled(! _disabledItem->isEnabled() );//此处能不能直接用item3了????????;//当然可以呀,但是需要把item3设置为成员变量,这样在lambda表达式中就能捕获到;//item3->setEnabled( !item3->isEnabled() );}); item4->setFontSizeObj(20); item4->setFontName("fonts/Marker Felt.ttf"); // Label Item (LabelBMFont) auto label = Label::createWithBMFont("fonts/bitmapFontTest3.fnt", "configuration"); auto item5 = MenuItemLabel::create(label, CC_CALLBACK_1(MenuLayerMainMenu::menuCallbackConfig, this)); // Testing issue #500 item5->setScale( 0.8f ); // Events MenuItemFont::setFontName("fonts/Marker Felt.ttf"); // Bugs Item auto item6 = MenuItemFont::create("Bugs", CC_CALLBACK_1(MenuLayerMainMenu::menuCallbackBugsTest, this)); // Font Item auto item7= MenuItemFont::create("Quit", CC_CALLBACK_1(MenuLayerMainMenu::onQuit, this)); auto item8 = MenuItemFont::create("Remove menu item when moving", CC_CALLBACK_1(MenuLayerMainMenu::menuMovingCallback, this)); //设置item7 "Quit"一闪一闪效果; auto color_action = TintBy::create(0.5f, 0, -255, -255); auto color_back = color_action->reverse(); auto seq = Sequence::create(color_action, color_back, nullptr); item7->runAction(RepeatForever::create(seq)); auto menu = Menu::create( item1, item2, item3, item4, item5, item6, item7, item8, nullptr); menu->alignItemsVertically(); //设置出场时动态效果; // elastic effect auto s = Director::getInstance()->getWinSize(); int i=0; for(const auto &child : menu->getChildren()) {//这里得到的是相应Menu的位置,其值是很小的,x轴基本上都是0,y轴从正到负(竖直排列从上往下); auto dstPoint = child->getPosition(); int offset = (int) (s.width/2 + 50); if( i % 2 == 0) offset = -offset; child->setPosition( Vec2( dstPoint.x + offset, dstPoint.y) );//EaseElasticOut效果 child->runAction( EaseElasticOut::create(MoveBy::create(2, Vec2(dstPoint.x - offset,0)), 0.35f) ); i++; } _disabledItem = item3; item3->retain(); _disabledItem->setEnabled( false ); addChild(menu); menu->setPosition(Vec2(s.width/2, s.height/2)); menu->setScale(0);//效果图从右上角出来时特别小,然后慢慢变大,通过ScaleTo实现这样就造成了从远到近的效果; menu->runAction(ScaleTo::create(1,1));}bool MenuLayerMainMenu::onTouchBegan(Touch *touch, Event * event){ return true;}void MenuLayerMainMenu::onTouchEnded(Touch *touch, Event * event){}void MenuLayerMainMenu::onTouchCancelled(Touch *touch, Event * event){}void MenuLayerMainMenu::onTouchMoved(Touch *touch, Event * event){}MenuLayerMainMenu::~MenuLayerMainMenu(){//FixedPriority需要手动释放监听 _eventDispatcher->removeEventListener(_touchListener); _disabledItem->release();}void MenuLayerMainMenu::menuCallback(Ref* sender){//LayerMultiplex是一个能够使它的子类进行复用的布景层类;//它支持一个或多个子类,但是一次仅能激活一个孩子;//下标从0开始; static_cast<LayerMultiplex*>(_parent)->switchTo(1);}void MenuLayerMainMenu::menuCallbackConfig(Ref* sender){ static_cast<LayerMultiplex*>(_parent)->switchTo(3);}void MenuLayerMainMenu::allowTouches(float dt){//还原; _eventDispatcher->setPriority(_touchListener, 1);//取消了所有定时器,不过对Actions的动作特效没有影响;//这里其实只要取消那个5s的定时器就好了; unscheduleAllSelectors(); log("TOUCHES ALLOWED AGAIN");}void MenuLayerMainMenu::menuCallbackDisabled(Ref* sender) { // hijack all touch events for 5 seconds//当前的zorder是0,这里设置成-1,他的优先级高;//所以这个时候_touchListener的四个函数touchBegan、touchMoved、TouchEnded、TouchCancelled优先被触发;//而这四个函数里面什么也没有干,只是把touchBegan返回true(一定要返回true不然就会往下传递了,因为我们设置了setSwallowTouches(true));//这样就形成了一个天然的触摸屏蔽了; _eventDispatcher->setPriority(_touchListener, -1);//5秒过后,在allowTouches()回调里面在设置回来了; schedule(schedule_selector(MenuLayerMainMenu::allowTouches), 5.0f); log("TOUCHES DISABLED FOR 5 SECONDS");}
看上面的注释,我们能知道怎么屏蔽触摸穿透,怎么又能恢复触摸事件,并且也展示了MenuItem的各种使用方法,大家在用的时候去看下源码接口就知
道怎么使用了,里面那个屏蔽触摸是5s内任务触摸无效,5s后就一切正常,场景出来的画面也很有意思。
效果图:
前面在讲Layer时我们说过LayerMultiplex 会在这里讲解,老实说这个类方法在切换layer时没有任何过渡效果,感觉有点鸡肋,但总还是有他的用处,喜
欢的就用,不喜欢的就不用,他是一个把多个layer层添加在一起的一个容器,他里面是互斥的一次只能激活(显示)一个layer,但是其他的layer里面设置
依然保存,也就是上一次是什么样子的,下一次切换回来时依然是那个样子。
下面看简单的代码:
void MenuTestScene::runThisTest(){ MenuItemFont::setFontSize(20); //产生了各种layer层,然后在下面全添加到LayerMultiplex中存放。 auto layer1 = new MenuLayerMainMenu(); auto layer2 = new MenuLayer2(); auto layer3 = new MenuLayer3(); auto layer4 = new MenuLayer4(); auto layer5 = new BugsTest(); auto layer6 = new RemoveMenuItemWhenMove();/*在这里创建的LayerMultiplex;一个能够使它的子类进行复用的布景层类。 功能: 它支持一个或多个子类;一次仅能激活一个孩子; */ auto layer = LayerMultiplex::create(layer1, layer2, layer3, layer4, layer5, layer6, nullptr); addChild(layer, 0); //?????为什么要手动release layer1->release(); layer2->release(); layer3->release(); layer4->release(); layer5->release(); layer6->release(); Director::getInstance()->replaceScene(this);}
这样加完后,中间很多代码像Lyaer2、Layer3、Layer4等代码这里都省略了,大家想看直接去cpp-tests例子下面MenuTest里面去看
效果图如下:
========================================================
当没有切换Layer层的时候,刚开始出来的Layer上"Quit"菜单是有动态效果的,一闪一闪的,但是只要切换一次,在切回来就不会闪了,
也就是说使用LayerMultiplex时会使用运动的actions停止,这只适合于静态layer层,感觉太鸡肋了吧。
========================================================
- cpp-tests Node::Layer及Node::Menu
- cpp-tests Node及NodeTest
- cpp-tests Node::Label
- node
- Node
- Node
- Node
- Node
- node
- node
- node
- Node
- Node
- node
- Node
- node
- Node
- Node
- 元素浮动
- 网站的开发,主要是一些教育类的吧,呵呵
- 我们为什么要给图片添加ALT属性
- struts2 和 freemarker 的防止表单重复提交
- 计算机编程语言编辑
- cpp-tests Node::Layer及Node::Menu
- 计算机编程语言编辑
- 闭包
- 2014最牛突破网站优化的瓶颈
- 基于内容的图像检索技术(1)
- 闭包最好的解释
- boot给kernel传递的参数,UIMAGE以及MTD
- getsockopt/setsockopt 函数说明
- 如果通过优化来提高SEO的效果