日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Cocos2d-x 3.2:通过ClippingNode实现一个功能完善的跑马灯公告(1)

發(fā)布時間:2023/11/29 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cocos2d-x 3.2:通过ClippingNode实现一个功能完善的跑马灯公告(1) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Cocos2d-x 3.2:通過ClippingNode實現(xiàn)一個功能完善的跑馬燈公告(1)

本文轉(zhuǎn)載至深入理解Cocos2d-x 3.x:一步一步通過ClippingNode實現(xiàn)一個功能完善的跑馬燈公告(1)

?

這篇文章主要是通過一步一步實現(xiàn)一個功能完善的跑馬燈公告來展示ClippingNode的用法并且最終深入ClippingNode的源碼,了解其實現(xiàn)原理。

首先,先介紹一下ClippingNode,ClippingNode也叫裁剪節(jié)點,能將一些內(nèi)容通過使用模板裁剪出來顯示在界面上,可以實現(xiàn)一些很炫酷的效果。來看看今天要實現(xiàn)的效果


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,這個方法是用于創(chuàng)建一個ClippingNode,這個就不多做贅述了,第二個create是創(chuàng)建一個帶遮罩模板的裁剪節(jié)點。

接下來的getStencil和setStencil分別是獲取和設(shè)置一個遮罩模板,裁剪物體方法就是通過這個遮罩模板的,遮罩模板只要是基于Node的對象都可以(非常重要)。

接下來的hasContent返回其是否有需要繪制的內(nèi)容,如果沒有繪制的內(nèi)容則返回false,有則返回true。

getAlphaThreshold 和setAlphaThreshold分別是獲取和設(shè)置一個像素的透明度值,取值范圍從0-1,其中0表示都不繪制,1表示都繪制。0.5表示透明度在 0.5以上的都繪制,這個函數(shù)涉及到opengl的Alpha測試的相關(guān)概念,Alpha測試的作用通過一句話解釋就是:所有像素的透明度值低于某個閥值 的統(tǒng)統(tǒng)拋棄,不繪制到屏幕上。

最后的isInverted和setInverted分別表示繪制的內(nèi)容是模板內(nèi)的還是模板外的,其效果如下:


2、簡易跑馬燈實現(xiàn)

上節(jié)簡單介紹了一下ClippingNode的函數(shù),這節(jié)就通過實現(xiàn)一個簡易的跑馬燈功能來直觀的了解。首先介紹一下制作跑馬燈的思路。

首先我們需要將跑馬燈中的一部分超出的字裁剪掉,不讓他顯示在界面上。這就需要用到ClippingNode,現(xiàn)在先來做第一步。實現(xiàn)的代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 //設(shè)置模板?? auto?stencil?=?Sprite::create();?? //設(shè)置顯示區(qū)域大小?? stencil->setTextureRect(Rect(0,?0,?50,?30));?? ??? //設(shè)置跑馬燈文字?? auto?text?=?Label::createWithSystemFont("-1dasdasdasd?efadaewfevgds?dfhrthrbgrg1-",?"",?24);?? //設(shè)置錨點?? text->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);?? ??? //創(chuàng)建裁剪節(jié)點?? auto?clippingNode?=?ClippingNode::create(stencil);?? //設(shè)置節(jié)點位置?? clippingNode->setPosition(Vec2(700,?400));?? //顯示模板內(nèi)的內(nèi)容?? clippingNode->setInverted(false);?? //添加顯示內(nèi)容?? clippingNode->addChild(text,?2);?? //加入到UI樹?? addChild(clippingNode);

上述的每一句代碼都有注釋,就不再多解釋了,這一步實現(xiàn)出來的效果如下圖,但是跑馬燈還不能動起來,待會我們就將跑馬燈動起來。

現(xiàn)在我們就設(shè)計一個Action將跑馬燈動起來,跑馬燈一般需要先將文字左移,移動到文字看不見的時候再將文字移除或者隱藏,代碼如下(為了簡便,就直接設(shè)置隱藏了):

1 2 auto?sequ?=?Sequence::create(MoveBy::create(5.0f,?Vec2(-text->getContentSize().width,?0)),?Hide::create(),?nullptr);?? text->runAction(sequ);

現(xiàn)在跑馬燈的樣子就如同開篇展示的那樣了,可是這樣還不能直接使用,因為這只是一串代碼,還需要對其進行一定的封裝,然后提供一個非常簡便的方法給別的類調(diào)用。


3、封裝

現(xiàn)在我們從便捷性的角度考慮如何將跑馬燈功能封裝成一個函數(shù)供其他類調(diào)用。首先提取出函數(shù)的參數(shù),分別是:顯示區(qū)域,跑馬燈文字,字體字號,跑馬燈位置,跑馬燈的父節(jié)點。下面是初步封裝好的一套跑馬燈函數(shù)的聲明:

1 void?showMarquee(Node*?parent,?const?std::string&?text,?const?std::string&?font,?float?fontSize,?const?Rect&?showRect,?const?Vec2&?position);

看參數(shù)是不是有些略多,每次調(diào)用這個函數(shù)是不是非常的不方便,那么我們現(xiàn)在來看看究竟有那些參數(shù)是必須要傳入的吧。每次調(diào)用跑馬燈顯示的文字都會改變,其他的參數(shù)在一個游戲中是不會改變的。那么就有必要做一個類來保證使用方法的便捷性了。

首先,我們簡單的構(gòu)建一下一個跑馬燈類,如下

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方法的實現(xiàn)

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()?? {?? ????//設(shè)置模板?? ????auto?stencil?=?Sprite::create();?? ????//設(shè)置顯示區(qū)域大小?? ????stencil->setTextureRect(_showRect);?? ??? ????//設(shè)置跑馬燈文字?? ????_label?=?Label::createWithSystemFont("",?_font,?_fontSize);?? ????//設(shè)置錨點?? ????_label->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);?? ??? ????_label->setAlignment(TextHAlignment::LEFT);?? ??? ????//創(chuàng)建裁剪節(jié)點?? ????auto?clippingNode?=?ClippingNode::create(stencil);?? ????//顯示模板內(nèi)的內(nèi)容?? ????clippingNode->setInverted(false);?? ????//添加顯示內(nèi)容?? ????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);?? }

這樣就可以通過以下的調(diào)用方法來調(diào)用跑馬燈了

1 2 3 4 Marquee*?m?=?Marquee::create();?? ????m->show("----hhahahah?veeeeee-----");?? ????m->setPosition(Vec2(700,?300));?? ????this->addChild(m);


4、完善

看 上去,此前的步驟我們已經(jīng)完成了一個跑馬燈的功能,實際上這個類距離真正能使用還差那么一點點,因為傳入跑馬燈的消息的傳入時機是不確定的,可能這一條消 息還沒有播放完成下一條就要開始播放了。這樣就需要實現(xiàn)一個播放等待隊列,將需要播放的消息加入播放隊列,然后跑馬燈自動判斷是否需要顯示。下面是改進后 的類聲明文件以及實現(xiàn)文件。

.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::queue<std::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()?? {?? ????//設(shè)置模板?? ????auto?stencil?=?Sprite::create();?? ????//設(shè)置顯示區(qū)域大小?? ????stencil->setTextureRect(_showRect);?? ??? ????//設(shè)置跑馬燈文字?? ????_label?=?Label::createWithSystemFont("",?_font,?_fontSize);?? ????//設(shè)置錨點?? ????_label->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);?? ??? ????_label->setAlignment(TextHAlignment::LEFT);?? ??? ????//創(chuàng)建裁剪節(jié)點?? ????auto?clippingNode?=?ClippingNode::create(stencil);?? ????//顯示模板內(nèi)的內(nèi)容?? ????clippingNode->setInverted(false);?? ????//添加顯示內(nèi)容?? ????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方法,內(nèi)部實現(xiàn)了一個有限狀態(tài)機,根據(jù)狀態(tài)來顯示剩余的消息,其使用方法與此前相似:

1 2 3 4 m?=?Marquee::create();?? m->addMessage("----hhahahah?veeeeee-----");?? m->setPosition(Vec2(700,?300));?? this->addChild(m);

?

轉(zhuǎn)載于:https://www.cnblogs.com/dudu580231/p/4560310.html

總結(jié)

以上是生活随笔為你收集整理的Cocos2d-x 3.2:通过ClippingNode实现一个功能完善的跑马灯公告(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。