~~~~我的生活,我的点点滴滴!!
性等等,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); }
效果图:
知道分别代表什么意思,怎么使用了。
下面代码列出了上面的使用方法:
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"); }
道怎么使用了,里面那个屏蔽触摸是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); }
当没有切换Layer层的时候,刚开始出来的Layer上"Quit"菜单是有动态效果的,一闪一闪的,但是只要切换一次,在切回来就不会闪了,
也就是说使用LayerMultiplex时会使用运动的actions停止,这只适合于静态layer层,感觉太鸡肋了吧。
========================================================