高埗网站仿做,wordpress文章添加回目录,网站建设推广seo,做亚马逊有哪些网站可以清货Cocos2d-x 3.2#xff1a;通过ClippingNode实现一个功能完善的跑马灯公告#xff08;1#xff09; 本文转载至深入理解Cocos2d-x 3.x#xff1a;一步一步通过ClippingNode实现一个功能完善的跑马灯公告#xff08;1#xff09; 这篇文章主要是通过一步一步实现一个功能完…Cocos2d-x 3.2通过ClippingNode实现一个功能完善的跑马灯公告1 本文转载至深入理解Cocos2d-x 3.x一步一步通过ClippingNode实现一个功能完善的跑马灯公告1 这篇文章主要是通过一步一步实现一个功能完善的跑马灯公告来展示ClippingNode的用法并且最终深入ClippingNode的源码了解其实现原理。 首先先介绍一下ClippingNodeClippingNode也叫裁剪节点能将一些内容通过使用模板裁剪出来显示在界面上可以实现一些很炫酷的效果。来看看今天要实现的效果 1、ClippingNode类分析 先来看看ClippingNode的声明文件 看看其中的public方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class CC_DLL ClippingNode : public Node { public: static ClippingNode* create(); static ClippingNode* create(Node *stencil); Node* getStencil() const; void setStencil(Node *stencil); virtual bool hasContent() const; GLfloat getAlphaThreshold() const; void setAlphaThreshold(GLfloat alphaThreshold); bool isInverted() const; void setInverted(bool inverted); }; 首先是create这个方法是用于创建一个ClippingNode这个就不多做赘述了第二个create是创建一个带遮罩模板的裁剪节点。 接下来的getStencil和setStencil分别是获取和设置一个遮罩模板裁剪物体方法就是通过这个遮罩模板的遮罩模板只要是基于Node的对象都可以非常重要。 接下来的hasContent返回其是否有需要绘制的内容如果没有绘制的内容则返回false有则返回true。 getAlphaThreshold 和setAlphaThreshold分别是获取和设置一个像素的透明度值取值范围从0-1其中0表示都不绘制1表示都绘制。0.5表示透明度在 0.5以上的都绘制这个函数涉及到opengl的Alpha测试的相关概念Alpha测试的作用通过一句话解释就是所有像素的透明度值低于某个阀值 的统统抛弃不绘制到屏幕上。 最后的isInverted和setInverted分别表示绘制的内容是模板内的还是模板外的其效果如下 2、简易跑马灯实现 上节简单介绍了一下ClippingNode的函数这节就通过实现一个简易的跑马灯功能来直观的了解。首先介绍一下制作跑马灯的思路。 首先我们需要将跑马灯中的一部分超出的字裁剪掉不让他显示在界面上。这就需要用到ClippingNode现在先来做第一步。实现的代码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 //设置模板 auto stencil Sprite::create(); //设置显示区域大小 stencil-setTextureRect(Rect(0, 0, 50, 30)); //设置跑马灯文字 auto text Label::createWithSystemFont(-1dasdasdasd efadaewfevgds dfhrthrbgrg1-, , 24); //设置锚点 text-setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); //创建裁剪节点 auto clippingNode ClippingNode::create(stencil); //设置节点位置 clippingNode-setPosition(Vec2(700, 400)); //显示模板内的内容 clippingNode-setInverted(false); //添加显示内容 clippingNode-addChild(text, 2); //加入到UI树 addChild(clippingNode); 上述的每一句代码都有注释就不再多解释了这一步实现出来的效果如下图但是跑马灯还不能动起来待会我们就将跑马灯动起来。 现在我们就设计一个Action将跑马灯动起来跑马灯一般需要先将文字左移移动到文字看不见的时候再将文字移除或者隐藏代码如下为了简便就直接设置隐藏了 1 2 auto sequ Sequence::create(MoveBy::create(5.0f, Vec2(-text-getContentSize().width, 0)), Hide::create(), nullptr); text-runAction(sequ); 现在跑马灯的样子就如同开篇展示的那样了可是这样还不能直接使用因为这只是一串代码还需要对其进行一定的封装然后提供一个非常简便的方法给别的类调用。 3、封装 现在我们从便捷性的角度考虑如何将跑马灯功能封装成一个函数供其他类调用。首先提取出函数的参数分别是显示区域跑马灯文字字体字号跑马灯位置跑马灯的父节点。下面是初步封装好的一套跑马灯函数的声明 1 void showMarquee(Node* parent, const std::string text, const std::string font, float fontSize, const Rect showRect, const Vec2 position); 看参数是不是有些略多每次调用这个函数是不是非常的不方便那么我们现在来看看究竟有那些参数是必须要传入的吧。每次调用跑马灯显示的文字都会改变其他的参数在一个游戏中是不会改变的。那么就有必要做一个类来保证使用方法的便捷性了。 首先我们简单的构建一下一个跑马灯类如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include cocos2d.h USING_NS_CC; class Marquee : public Node { public: CREATE_FUNC(Marquee); bool init(); void show(const std::string text); public: const std::string getFont() const { return _font; } void setFont(std::string font) { _font font; } float getFontSize() const { return _fontSize; } void setFontSize(float fontSize) { _fontSize fontSize; } public: const Rect getShowRect() const { return _showRect; } void setShowRect(Rect showRect) { _showRect showRect; } protected: Marquee() : _font(), _fontSize(24), _showRect(Rect(0,0,200,30)) {}; ~Marquee() {}; private: std::string _font; float _fontSize; Rect _showRect; }; 然后是最重要的init方法和show方法的实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 bool Marquee::init() { //设置模板 auto stencil Sprite::create(); //设置显示区域大小 stencil-setTextureRect(_showRect); //设置跑马灯文字 _label Label::createWithSystemFont(, _font, _fontSize); //设置锚点 _label-setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); _label-setAlignment(TextHAlignment::LEFT); //创建裁剪节点 auto clippingNode ClippingNode::create(stencil); //显示模板内的内容 clippingNode-setInverted(false); //添加显示内容 clippingNode-addChild(_label); //加入到UI树 addChild(clippingNode); return true; } void Marquee::show(const std::string text) { _label-setString(text); _label-setPosition(Vec2(0, _label-getContentSize().height / 2)); auto sequ Sequence::create(MoveBy::create(5.0f, Vec2(-_label-getContentSize().width, 0)), Hide::create(), nullptr); _label-runAction(sequ); } 这样就可以通过以下的调用方法来调用跑马灯了 1 2 3 4 Marquee* m Marquee::create(); m-show(----hhahahah veeeeee-----); m-setPosition(Vec2(700, 300)); this-addChild(m); 4、完善 看 上去此前的步骤我们已经完成了一个跑马灯的功能实际上这个类距离真正能使用还差那么一点点因为传入跑马灯的消息的传入时机是不确定的可能这一条消 息还没有播放完成下一条就要开始播放了。这样就需要实现一个播放等待队列将需要播放的消息加入播放队列然后跑马灯自动判断是否需要显示。下面是改进后 的类声明文件以及实现文件。 .h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #include cocos2d.h USING_NS_CC; class Marquee : public Node { public: enum class State { idle, playing, }; public: CREATE_FUNC(Marquee); bool init(); void addMessage(const std::string text); public: const std::string getFont() const { return _font; } void setFont(std::string font) { _font font; } float getFontSize() const { return _fontSize; } void setFontSize(float fontSize) { _fontSize fontSize; } public: const Rect getShowRect() const { return _showRect; } void setShowRect(Rect showRect) { _showRect showRect; } public: const State getState() const { return _state; } protected: Marquee() : _font(), _fontSize(24), _showRect(Rect(0,0,200,30)), _state(State::idle) {}; ~Marquee() {}; void show(const std::string text); private: State _state; private: std::string _font; float _fontSize; Rect _showRect; private: Label * _label; private: std::queuestd::string _texts; }; .cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include Marquee.h bool Marquee::init() { //设置模板 auto stencil Sprite::create(); //设置显示区域大小 stencil-setTextureRect(_showRect); //设置跑马灯文字 _label Label::createWithSystemFont(, _font, _fontSize); //设置锚点 _label-setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); _label-setAlignment(TextHAlignment::LEFT); //创建裁剪节点 auto clippingNode ClippingNode::create(stencil); //显示模板内的内容 clippingNode-setInverted(false); //添加显示内容 clippingNode-addChild(_label); //加入到UI树 addChild(clippingNode); stencil-setColor(Color3B::BLACK); addChild(stencil, -1); return true; } void Marquee::show(const std::string text) { _state State::playing; _label-setString(text); _label-setPosition(Vec2(0, 0)); auto sequ Sequence::create( Show::create(), MoveBy::create(5.0f, Vec2(-(_label-getContentSize().width _showRect.size.width / 2), 0)), Hide::create() , DelayTime::create(1.0f), CCCallFunc::create([]() { if (_texts.size() 0) { _state State::idle; } else { show(_texts.front()); _texts.pop(); } }), nullptr); _label-runAction(sequ); } void Marquee::addMessage(const std::string text) { if (text.empty()) { return; } if (_state State::idle) { show(text); } else { _texts.push(text); } } 此处将show方法隐藏并且提供了addMessage方法内部实现了一个有限状态机根据状态来显示剩余的消息其使用方法与此前相似 1 2 3 4 m Marquee::create(); m-addMessage(----hhahahah veeeeee-----); m-setPosition(Vec2(700, 300)); this-addChild(m); 转载于:https://www.cnblogs.com/dudu580231/p/4560310.html