Cocos2d-xUI组件详解

Cocos2d-xUI组件详解

标签(Label)

  Cocos2d-x提供Label对象给用户,可以使用位图字体,TrueType字体,系统字体创建标签。这个单一的类能处理你所有的标签需求。下面介绍使用各种字体,创建标签的方法。

效果图

BMFont

  BMFont是一个使用位图字体创建的标签类型,位图字体中的字符由点阵组成。使用这种字体标签性能非常好,但是不适合缩放。由于点阵的原因,缩放会导致失真。标签中的每一个字符都是一个单独的Sprite,也就是说精灵的属性(旋转,缩放,着色等)控制都适用于这里的每个字符。

  创建BMFont标签需要两个文件,.fnt文件和.png文件。可以使用像Glyph Designer这样的工具来创建位图字体,这些文件将会自动生成。

  使用位图字体创建标签:

auto myLabel = Label::createWithBMFont("bitmapRed.fnt","Your Text");

效果图

  所有在标签中出现的字符都应该能在提供的.fnt文件找到,如果找不到,字符就不会被渲染。如果你渲染了一个Label,同时它有丢失字符,记得去查看一下,.fnt文件是否完备。

TTF

  True Type字体和我们上面了解的位图字体不同,使用这种字体很方便,你不需要为每种尺寸和颜色单独使用字体文件。不像BMFont,如果想不失真的缩放,就要提供多种字体文件。

  要创建这种标签,需要制定.ttf字体文件名,文本字符串和字体大小。

  使用TrueType字体创建标签:

auto myLabel = Label::createWithTTF("Your Text","Marker Felt.ttf",24);

效果图

  虽然使用TruType字体比使用位图字体更灵活、但是它渲染速度较慢,并且更改标签的属性(字体,大小)是一项非常消耗性能的操作。

  如果需要具有相同属性的多个Label对象,那可以创建一个TTFConfig对象来统一配置,TTFConfig对象允许设置所有标签的共同属性。

  通过以下方式创建一个TTConfig对象:

//为所有的Label标签创建一个TTFConfig共享文件配置
TTFConfig labelConfig;
labelConfig.fontFilePath = "myFont.ttf";
labelConfig.fontSize = 16;
labelConfig.glyphs = GlyphCollection::DYNAMIC;
labelConfig.outlineSize = 0;
labelConfig.customGlyphs = nullptr;
labelConfig.distanceFieldEnabled = false;

//从TTFConfig文件中创建TTF Label标签
auto myLabel = Label::createWithTTF(labelConfig,"My Label Text");

效果图

  TTFConfig也能用于展示中文,日文,韩文的字符。

SystemFont

  SystemFont是一个使用系统默认字体,默认字体大小的标签类型,这样的标签不要改变它的属性,它会使用系统的规则。

  使用系统字体创建标签:

auto myLabel = Label::createWithSystemFont("My Label Text","Arial",16);

效果图

标签效果

  在屏幕上有标签后,它们可能看起来很普通,这时希望让它们变得更加漂亮。不用创建自定义字体!Label对象就可以对标签应用效果,包括阴影,描边,发光。

  阴影效果:

auto myLabel = Label::createWithTTF("myFont.ttf","My Label Text",16);

//所有标签类型都支持阴影效果
myLabel->enableShadow();

效果图

  描边效果:

auto myLabel = Label::createWithTTF("myFont.ttf","My Label Text",16);

//描边效果仅支持TTF字体,而且需要指定所需的颜色
myLabel->enableOutline(Color4B::WHITE,1);

效果图

  发光效果:

auto myLabel = Label::createWithTTF("myFont.ttf","My Label Text",16);

//发光效果仅支持TTF字体,而且需要指定所需的颜色
myLabel->enabelGlow(Color4B::YELLOW);

效果图

实例
  • 使用文本标签实现打字机效果,要求:
    • 控制每行字数自动换行
    • 文字字体使用方正姚体
    • 字体加粗
    • 字体颜色粉红色
    • 实现打字机效果
演示效果

效果图

示例代码如下
json文件

使用json文件主要是解决中文乱码的问题,详见链接:https://blog.csdn.net/qq135595696/article/details/122850029

效果图

HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include <string>

class HelloWorld : public cocos2d::Scene
{
public:
    static cocos2d::Scene* createScene();

    virtual bool init();
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);

private:
    //记录当前文字内容
    std::string prt_content;
    cocos2d::Label* prt_label;
};

#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
#include "LayerDemo.h"
//引入cJson库文件
#include "cJSON.h"

#include <fstream>//C++IO流头文件

USING_NS_CC;
using namespace std;

Scene* HelloWorld::createScene()
{
	return HelloWorld::create();
}

// Print useful error message instead of segfaulting when files are not there.
static void problemLoading(const char* filename)
{
	printf("Error while loading: %s\n", filename);
	printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HelloWorldScene.cpp\n");
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
	if (!Scene::init())
		return false;
    
	auto visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();

    //读取test.json文件内容
	FILE* pFile = fopen("test.json", "r");
	if (nullptr == pFile)
	{
		problemLoading("test.json");
		return false;
	}

	char testContent[1024 * 20]{ 0 };
	while (!feof(pFile))
	{
		char buffer[1024]{ 0 };
		fgets(buffer, 1024, pFile);
		int index = strlen(testContent);
		for (int i = 0; i < strlen(buffer); i++)
		{
			if (buffer[i] == '\n')
				break;
			testContent[index++] = buffer[i];
		}
	}

	//解析test.json文件内容
	cJSON* monitor = cJSON_Parse(testContent);//将字符串转换为json对象
	if (nullptr == monitor)
		return false;

    //获取key为mainKey1的对象内容
	cJSON* mainKey1 = cJSON_GetObjectItem(monitor, "mainKey1");
    
    //获取key为value的对象内容
	auto value1 = cJSON_GetObjectItem(mainKey1, "value");
	
    //输出打印value对象的内容
	log(value1->valuestring);

	//实现背景图片
	auto sprite = Sprite::create("1.jpg");
	sprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
	sprite->setPosition(Vec2(visibleSize / 2));
	sprite->setScale(0.3);
	this->addChild(sprite);

	//显示文字内容
	prt_content = value1->valuestring;
	//开始不显示任何内容
	prt_label = Label::create(prt_content, "方正姚体", 30);
	prt_label->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
	prt_label->setPosition(Vec2(visibleSize / 2));
	prt_label->setColor(Color3B(248, 248, 255));
	prt_label->enableBold();
	prt_label->setDimensions(400.0f, 0);//使用纯英文换行失效,只有存在中文才可能生效!
	this->addChild(prt_label);


	//实现打字效果
	static int i = 0;
	this->schedule([&](float dlt) {
		char ch = prt_content[i];
		//获取当前下标的字符
		if (ch < 0 && ch > -128)
			//在utf-8编码中一个中文占三个字节,在ANSI编码中一个中文占2个字节,在utf-16中一个中文占4个字节
			i += 3;
		else
			i++;
        //截取字符串
		string str = prt_content.substr(0, i);
		prt_label->setString(str);
		
		if (i > prt_content.length())
			this->unschedule("scheduleCallback");//停止定时器
		}, 0.1f, "scheduleCallback");
	return true;
}

菜单(Menu)

  • 继承自Layer类,是一个层容器

效果图

效果图

  在每个游戏中都会有菜单。我们使用菜单浏览游戏选项,更改游戏设置。菜单通常包含开始,退出,设置,关于等项,菜单当然也可以包含子菜单。在Cocos2d-x提供Menu对象支持菜单功能,Menu对象是一种特殊的Node对象。

  创建一个菜单用于添加菜单项:

auto myMenu = Menu::create();

  像我们刚才提到的一个菜单,总会有一些菜单项,比如开始,退出,设置等,没有菜单项的菜单没有存在的意义。Cocos2d-x提供了一些方法来创建菜单项,比如使用Label对象,或是使用一张图像。菜单项一般由正常状态和选择状态。菜单项显示是正常状态,当你点击时变为选择状态,同时点击菜单还会触发一个回调函数

  使用图像创建菜单:

//通过指定的图像创建菜单项
auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));

auto menu = Menu::create(closeItem,NULL);
this->addChild(menu,1);

  还可以使用MenuItem的一个vector创建菜单:

//创建一个vector来管理menuItems
Vector<MenuItem*> MenuItems;

auto closeItem = MenuItemImage::craete("CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));

MenuItems.pushBack(closeItem);

auto menu = Menu::createWithArray(MenuItems);
this->addChild(menu,1);

使用Lambda表达式

  当点击菜单项时会触发一个回调函数。C++11支持了lambda表达式,lambda表达式时匿名函数,所以可以在回调方法处使用lambda表达式,这样能让代码看起来更简单,同时不会有额外的性能开销。

  一个简单的lambda表达式:

//创建一个简单的lambda表达式
auto func = [](){cout<<"Hello World";};

//执行该函数
func();

  使用lambda表达式作为菜单项的回调函数:

auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",[&](Ref* sender){
    //执行我们需要的逻辑
});

按钮(Button)

  按钮在我们点击后会使我们的游戏产生一些变化,比如更改了场景,触发了动作等。按钮会拦截点击事件,事件触发时调用事先定义好的回调函数。按钮有一个正常状态,一个选择状态,还有一个不可点击状态,按钮的外观可以根据这三个状态而改变。Cocos2d-x提供Button对象支持按钮功能,创建一个按钮并定义一个回调函数很简单,但是需要在操作的时候要有头文件需包含:#include"ui/CocosGUI.h"

auto button = Button::create("normal_image.png","selected_image.png","disabled_image.png");

button->setTitleText("Button Text");

button->addTouchEventListener([&](Ref* sender,Widget::TouchEventType type){
    switch(type)
    {
        case ui::Widget::TouchEventType::BEGAN:
            break;
        case ui::Widget::TouchEventType::ENDED:
            std::cout<<"Button 1 clicked"<<std::endl;
            break;
        default:
            break;
    }
});

this->addChild(button);

  可以看到,我们为按钮的每个状态都制定了一个.png图像:

效果图

  在屏幕显示的时候,同一个时刻只能看到一个状态,正常显示状态像这样:

效果图

复选框(CheckBox)

  日常生活中复选框很常见,比如填写问卷时,让我们选一些喜欢的项目,游戏设置中,某一设置时打开还是关闭。只有两种状态的项目经常被设计为复选框。Cocos2d-x提供Checkbox对象支持复选框功能。

  创建一个复选框:

#include "ui/CocosGUI.h"

auto checkbox = CheckBox::create("check_box_normal.png",
                                "check_box_normal_press.png",
                                "check_box_active.png",
                                "check_box_normal_disable.png",
                                "check_box_active_disable.png");

checkbox->addTouchEventListener([&](Ref* sender,Widget::TouchEventType type){
    switch(type)
    {
        case ui::Widget::TouchEventType::BEGAN:
            break;
        case ui::Widget::TouchEventType::ENDED:
            std::cout<<"check 1 clicked"<<std::endl;
            break;
        default:
            break;
    }
});

this->addChild(checkbox);

  在上面的例子中,我么能看到一个复选框制定了五张图像,因为复选框有五种状态,未被选中,被点击,未被选中时不可用,被选中,选中时不可用。这样五种状态的图像依次如下:

效果图

  在频幕显示的时候,同一个时刻只能看到一个状态,被选中时状态像这样:

效果图

进度条(LoadingBar)

  如果你经常玩游戏,那肯定见过一个情景:屏幕上显示了一个进度条,提示资源正在加载中,这个条表示资源加载的进度。Cocos2d-x提供LoadingBar对象支持进度条。

  创建一个进度条:

#include "ui/CocosGUI.h"

auto loadingBar = LoadingBar::create("LoadingBarFile.png");

//设置进度条的加载方向
loadingBar->setDirection(LoadingBar::Direction::RIGHT);

this.addChild(loadingBar);

  上面的例子,我们创建了一个进度条,设置了当进度条增加时,进度条向右填充。

  在进度的控制中,肯定需要改变进度条的进度,示例如下:

#include "ui/CocosGUI.h"

auto loadingBar = LoadingBar::craete("LoadingBarFile.png");
loadingBar->setDirection(LoadingBar::Direction::RIGHT);


//触发事件,改变进度条的百分比
loadingBar->setPercent(25);

//再次改变
loadingBar->setPercent(35);

this->addChild(loadingBar);

  上面的例子,使用的进度条图像是:

效果图

  在屏幕上一个满进度的进度条是这样的:

效果图

滑动条(Slider)

  有时候你想平滑的改变一个值,比如游戏设置中,调整背景音乐的音量,或者你有一个角色,允许用户设置攻击敌人的力量。这种场景最适合使用滑动条,Cocos2d-x提供Slider对象支持滑动条。

  创建滑动条:

#include "ui/CocosGUI.h"

auto slider = Slider::create();
slider->loadBarTexture("Slider_Back.png");//滑动条看起来像什么
slider->loadSlidBallTextures("SliderNode_Normal.png","SliderNode_Press.png","SliderNode_Disable.png");
slider->loadProgressBarTexture("Slider_PressBar.png");

slider->addTouchEventListener([&](Ref* sender,Widget::TouchEventType type){
   switch(type)
   {
           case ui::Widget::TouchEventType::BEGAN:
                   break;
           case ui::Widget::TouchEventType::ENDED:
                   std::cout << "slider moved" << std::endl;
                   break;
           default:
                   break;
   }
});

this->addChild(slider);

  从上面的例子,可以看出,实现一个滑动条需要提供五张图像,对应滑动条的不同部分不同状态,分别为:滑动条背景,上层进度条,正常显示时的滑动端点,滑动式的滑动端点,不可用时的滑动端点。本次示例的五张图如下:

效果图

  在屏幕上一个滑动条看起来是这样的:

效果图

文本框(TextField)

  如果你想让参与游戏的玩家可以自定义一个昵称怎么办,在哪里输入文本?Cocos2d-x提供TextField满足这种需求。它支持触摸事件,焦点,定位内容百分比等。

  创建一个文本框:

#include "ui/CocosGUI.h"

auto textField = TextField::craete("","Arial",30);

textField->addTouchEventListener([&](Ref* sender,Widget::TouchEventType type){
   std::cout<<"editing a TextField"<<std::endl; 
});

this->addChild(textField);

  这个例子中,创建了一个TextField,指定了回调函数。

  提供的文本对象,是多功能的,能满足所有的输入需求,比如用户密码的输入,限制用户可以输入的字符数等等!

  看一个例子:

#include "ui/CocosGUI.h"

auto textField = TextField::craete("","Arial",30);

//启动此文本字段密码
textField->setPasswordEnabled(true);

//设置用户可以输入此文本字段的最大字符数
textField->setMaxLength(10);

textField->addTouchEventListener([&](Ref* sender,Widget::TouchEventType type){
    std::cout << "editing a TextField" << std::endl;
});

this->addChild(textField);

  屏幕上一个文本框是这样的:

效果图

  当点击文本框,键盘就会自动调出来,此时可以输入文本:

效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ufgnix0802

总结不易,谢谢大家的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值