对于UI界面,目前常用的有字体显示,标签,菜单,进度条,调度器,自定义文字按钮,自定义拖动进度条。(后续添加)
我们的代码都是直接在新建项目HelloWorld中的HelloWorldScene.cpp的init()函数中操作。
<span style="font-size:18px;">CCSize s = CCDirector::sharedDirector()->getWinSize(); // !!!!!字体以及标签!!!!! // 参数:1、要显示文字;2、显示字体;3、字体大小 CCLabelTTF *ttf = CCLabelTTF::create("windows7lake","A Damn Mess.ttf",32); ttf->setPosition(100,s.height - 10); addChild(ttf); // 参数:1、要显示文字;2、显示字体;3、字体大小;4、尺寸(把这一段字符串看作整体, // 需要显示的大小);5、屏幕横向位置;6、屏幕纵向位置 Label *ttf1 = Label::createWithSystemFont("windows7",42,Size::Size(70,40),TextHAlignment::CENTER,TextVAlignment::TOP); ttf1->setPosition(100,s.height - 60); addChild(ttf1); // 参数:1、要显示文字;2、显示字体的相对路径 LabelBMFont *ttf2 = LabelBMFont::create("lake","fonts/bitmapFontChinese.fnt"); ttf2->setPosition(50,s.height - 110); addChild(ttf2); // 参数:1、要显示文字;2、显示字体的相对路径; LabelAtlas *ttf3 = LabelAtlas::create("123 Test","fonts/tuffy_bold_italic-charmap.plist"); ttf3->setPosition(50,s.height - 160); addChild(ttf3); // 参数:1、要显示文字;2、显示字体的相对路径;3、字体宽度;4、字体高度;5、字体图片中的起始符号(这里为空格) LabelAtlas *ttf4 = LabelAtlas::create("456 Test","fonts/tuffy_bold_italic-charmap.png",24,32,' '); ttf4->setPosition(50,s.height - 210); addChild(ttf4); // 字体配置参数:1、字体;2、字体大小 TTFConfig config("fonts/arial.ttf",16); // 参数:1、字体配置;2、显示字符;3、相对横向位置 Label *ttf5 = Label::createWithTTF(config,"789 test",TextHAlignment::RIGHT); ttf5->setPosition(50,s.height - 250); this->addChild(ttf5); // 参数:显示字体的相对路径 Label *ttf6 = Label::createWithCharMap("fonts/tuffy_bold_italic-charmap.plist"); addChild(ttf6); ttf6->setPosition(50,s.height - 290);</span>运行结果:
菜单:
<span style="font-size:18px;">CCSize s = CCDirector::sharedDirector()->getWinSize(); // !!!!!菜单!!!!! // Sprite Item auto spriteNormal = Sprite::create("image/HelloWorld.png",Rect(0,23 * 2,115,23)); auto spriteSelected = Sprite::create("image/HelloWorld.png",23 * 1,23)); auto spriteDisabled = Sprite::create("image/HelloWorld.png",23 * 0,23)); MenuItemSprite *item1 = MenuItemSprite::create(spriteNormal,spriteSelected,spriteDisabled,CC_CALLBACK_1(HelloWorld::menuCallback,this)); // Image Item MenuItemImage *item2 = MenuItemImage::create("CloseNormal.png","CloseSelected.png",this)); // Font Item MenuItemFont *item3 = MenuItemFont::create("Lake",this)); // Label Item LabelAtlas *labelAtlas = LabelAtlas::create("0123456789",16,'.'); MenuItemLabel *item4 = MenuItemLabel::create(labelAtlas,this)); Menu *menu = Menu::create(item1,item2,item3,item4,nullptr); menu->alignItemsVertically(); menu->setPositionX(300); addChild(menu);</span>运行结果:
进度条:
<span style="font-size:18px;">CCSize s = CCDirector::sharedDirector()->getWinSize(); // !!!!!进度条!!!!! Sequence *s1 = Sequence::createWithTwoActions( ProgressTo::create(4,100),ProgressTo::create(0,0)); Sequence *s2 = Sequence::createWithTwoActions( ProgressTo::create(4,0)); CCProgressTimer *pt1 = CCProgressTimer::create(Sprite::create("HelloWorld.png")); CCProgressTimer *pt2 = CCProgressTimer::create(Sprite::create("HelloWorld.png")); // 设置旋转进度条 //pt1->setType(CCProgressTimer::Type::RADIAL); // 设置直线进度条 pt1->setType(CCProgressTimer::Type::BAR); // 设置扩展的点 pt1->setMidpoint(Vec2(1,0)); // 设置x轴或y轴扩展 pt1->setBarChangeRate(Vec2(1,0)); pt1->setPosition(100,100); pt1->runAction(Repeat::create(s1,1)); addChild(pt1); // 设置旋转进度条 //pt2->setType(CCProgressTimer::Type::RADIAL); //// 设置反向旋转进度条 //pt2->setReverseProgress(true); // 设置直线进度条 pt2->setType(CCProgressTimer::Type::BAR); pt2->setMidpoint(Vec2(0,0)); pt1->setBarChangeRate(Vec2(0,1)); pt2->setPosition(s.width - 100,100); pt2->runAction(Repeat::create(s2,1)); addChild(pt2);</span>
运行结果:
调度器:
<span style="font-size:18px;">HelloWorldScene.h void update(float dt) override;</span>
<span style="font-size:18px;">init() { // 随着游戏帧率不断输出,默认调用重载的update()函数 //scheduleUpdate(); // 参数:1、时间调度选择器,里面是回调函数;2、每次间隔时间;3、调用次数; // 4、第一次触发之前的延迟时间 //schedule(schedule_selector(HelloWorld::update),1.0f,kRepeatForever,0); // 只调用一次,第二个参数为触发之前的延迟时间 scheduleOnce(schedule_selector(HelloWorld::update),0.1f); } void HelloWorld::update(float dt) { log("update"); }</span>
新建TextButton.h:
<pre name="code" class="cpp">#ifndef __TEXTBUTTON_H__ #define __TEXTBUTTON_H__ #include "cocos2d.h" #include "ui/CocosGUI.h" using namespace cocos2d; using namespace cocos2d::ui; class TextButton : public cocos2d::Label { public: // 创建按钮 static TextButton *create(const std::string& text,const std::function<void(TextButton*)> &onTriggered); // 设置是否可以点击 void setEnabled(bool enabled); CREATE_FUNC(TextButton); private: // 触发器 std::function<void(TextButton*)> _onTriggered; bool _enabled; TextButton(); // 判断点击的点是否在按钮范围内 bool touchHits(Touch* touch); bool onTouchBegan(Touch* touch,Event* event); void onTouchEnded(Touch* touch,Event* event); void onTouchCancelled(Touch* touch,Event* event); // 放大缩小按钮 void ScaleButtonTo(float scale); }; #endif // !__TEXTBUTTON_H__
TextButton.cpp:
#include "TextButton.h" TextButton* TextButton::create(const std::string& text,const std::function<void(TextButton*)> &onTriggered) { // 建立一个按钮对象 auto ret = new (std::nothrow) TextButton(); // 标签设置 TTFConfig ttfconfig("fonts/arial.ttf",25); if (ret && ret->setTTFConfig(ttfconfig)) { ret->setString(text); // 设置触发器 ret->_onTriggered = onTriggered; // 自动释放 ret->autorelease(); return ret; } delete ret; return nullptr; } void TextButton::setEnabled(bool enabled) { _enabled = enabled; if (_enabled) { this->setColor(Color3B::WHITE); } else { this->setColor(Color3B::GRAY); } } TextButton::TextButton() : _onTriggered(nullptr),_enabled(true) { // 建立监听器并设置触摸监听 auto listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(true); listener->onTouchBegan = CC_CALLBACK_2(TextButton::onTouchBegan,this); listener->onTouchEnded = CC_CALLBACK_2(TextButton::onTouchEnded,this); listener->onTouchCancelled = CC_CALLBACK_2(TextButton::onTouchCancelled,this); // 将监听加入发送器 _eventDispatcher->addEventListenerWithSceneGraPHPriority(listener,this); } bool TextButton::touchHits(Touch* touch) { // 将屏幕坐标转换为Cocos2d坐标(OpenGL坐标) auto hitPos = this->convertToNodeSpace(touch->getLocation()); // 判断点击范围是否在文字按钮范围 if (hitPos.x >= 0 && hitPos.y >= 0 && hitPos.x <= _contentSize.width && hitPos.y <= _contentSize.height) { return true; } return false; } bool TextButton::onTouchBegan(Touch* touch,Event* event) { auto hits = touchHits(touch); if (hits) { // 缩小按钮0.95倍 ScaleButtonTo(0.95); } return hits; } void TextButton::onTouchEnded(Touch* touch,Event* event) { if (_enabled) { auto hits = touchHits(touch); if (hits && _onTriggered) { // 为按钮添加触发器 _onTriggered(this); } } ScaleButtonTo(1); } void TextButton::onTouchCancelled(Touch* touch,Event* event) { ScaleButtonTo(1); } void TextButton::ScaleButtonTo(float scale) { // 创建缩放动画 auto action = ScaleTo::create(0.05f,scale); action->setTag(10000); stopActionByTag(10000); runAction(action); }
自定义拖动进度条:
新建SliderProgress.h:
#ifndef __SLIDERPROGRESS_H__ #define __SLIDERPROGRESS_H__ #include "cocos2d.h" #include "ui/CocosGUI.h" using namespace cocos2d; using namespace cocos2d::ui; class SliderProgress : public Slider { public: enum class TouchEvent { DOWN,MOVE,UP,CANCEL }; // 定义回调对象 typedef std::function<void(SliderProgress*,float,TouchEvent)> ccSliderProgressCallBack; static SliderProgress* create(); // 设置回调函数 void setCallBack(const ccSliderProgressCallBack& callback); // 设置进度条进度 void setRatio(float ratio); virtual bool onTouchBegan(Touch* touch,Event* unusedEvent) override; virtual void onTouchMoved(Touch *touch,Event *unusedEvent) override; virtual void onTouchEnded(Touch *touch,Event *unusedEvent) override; virtual void onTouchCancelled(Touch *touch,Event *unusedEvent) override; private: // 触摸事件的类型 TouchEvent _touchEvent; // 进度条的比率,范围0.0f-1.0f float _ratio; // 回调功能函数 ccSliderProgressCallBack _callback; }; #endif // !__SLIDERPROGRESS_H__
SliderProgress.cpp:
#include "SliderProgress .h" SliderProgress* SliderProgress::create() { auto ret = new (std::nothrow) SliderProgress(); if (ret && ret->init()) { ret->_callback = nullptr; // 将图片缓存到纹理缓存 ret->loadBarTexture("slider/sliderTrack.png"); ret->loadSlidBallTextures("slider/sliderThumb.png","slider/sliderThumb.png",""); ret->loadProgressBarTexture("slider/sliderProgress.png"); ret->autorelease(); return ret; } CC_SAFE_DELETE(ret); return ret; } void SliderProgress::setCallBack(const ccSliderProgressCallBack& callback) { _callback = callback; } void SliderProgress::setRatio(float ratio) { if (ratio > 1.0f) { ratio = 1.0f; } else if (ratio < 0.0f) { ratio = 0.0f; } _ratio = ratio; _percent = 100 * _ratio; // 获得当前Slider移动图标点ball距离左边起点水平方向的长度 float dis = _barLength*_ratio; // 设置移动图标点ball的位置 _slidBallRenderer->setPosition(Vec2(dis,_contentSize.height / 2.0f)); if (_scale9Enabled) { // 设置进度条的长度 _progressBarRenderer->setPreferredSize(Size(dis,_progressBarTextureSize.height)); } else { // 从先前加载的图片纹理缓存中取出图片精灵Slider进度条 auto spriteRenderer = _progressBarRenderer->getSprite(); if (nullptr != spriteRenderer) { // 返回精灵Slider进度条的边框矩形 Rect rect = spriteRenderer->getTextureRect(); // 从进度条缓存里面取出宽度*比率=矩形的宽度 rect.size.width = _progressBarTextureSize.width * _ratio; // 设置精灵Slider进度条的边框矩形缓存 spriteRenderer->setTextureRect(rect,spriteRenderer->isTextureRectRotated(),rect.size); } } } bool SliderProgress::onTouchBegan(Touch* touch,Event* unusedEvent) { auto ret = Slider::onTouchBegan(touch,unusedEvent); if (ret &&_callback) { _touchEvent = TouchEvent::DOWN; // 将接受的坐标转换为本地坐标 Vec2 nsp = convertToNodeSpace(_touchBeganPosition); _ratio = nsp.x / _barLength; if (_ratio < 0.0f) { _ratio = 0.0f; } else if (_ratio > 1.0f) { _ratio = 1.0f; } // 设置回调函数 _callback(this,_ratio,_touchEvent); } return ret; } void SliderProgress::onTouchMoved(Touch *touch,Event *unusedEvent) { _touchEvent = TouchEvent::MOVE; Slider::onTouchMoved(touch,unusedEvent); Vec2 nsp = convertToNodeSpace(_touchMovePosition); _ratio = nsp.x / _barLength; if (_ratio < 0.0f) _ratio = 0.0f; else if (_ratio > 1.0f) _ratio = 1.0f; if (_callback){ _callback(this,_touchEvent); } } void SliderProgress::onTouchEnded(Touch *touch,Event *unusedEvent) { _touchEvent = TouchEvent::UP; Slider::onTouchEnded(touch,unusedEvent); Vec2 nsp = convertToNodeSpace(_touchEndPosition); _ratio = nsp.x / _barLength; if (_ratio < 0.0f) _ratio = 0.0f; else if (_ratio > 1.0f) _ratio = 1.0f; if (_callback){ _callback(this,_touchEvent); } } void SliderProgress::onTouchCancelled(Touch *touch,Event *unusedEvent) { _touchEvent = TouchEvent::CANCEL; Slider::onTouchCancelled(touch,unusedEvent); if (_callback){ _callback(this,_touchEvent); } }
自定义控件的使用,HelloWorldScene.cpp:
#include "HelloWorldScene.h" #include "TextButton.h" #include "SliderProgress .h" USING_NS_CC; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if (!Layer::init()) { return false; } auto okbutton = TextButton::create("ok",[&](TextButton* textbutton){ auto ttfLabel = LabelTTF::create("Are you sure?","arial.ttf",32); ttfLabel->setPosition(200,250); ttfLabel->setTag(1111); this->addChild(ttfLabel); }); okbutton->setPosition(170,290); addChild(okbutton); auto cancellbutton = TextButton::create("cancell",[&](TextButton* textbutton){ removeChildByTag(1111,true); }); cancellbutton->setPosition(270,290); addChild(cancellbutton); label = Label::create("LAKE",50); label->setPosition(240,100); addChild(label); auto slider = SliderProgress::create(); slider->setPercent(100); slider->setCallBack([&](SliderProgress* se,float ratio,SliderProgress::TouchEvent event) { label->setDimensions(150 * ratio,150 * ratio); }); slider->setPosition(Vec2(240,200)); addChild(slider); return true; } void HelloWorld::menuCloseCallback(Ref* pSender) { Director::getInstance()->end(); }
运行结果: