Cocos2d-x学习笔记:完全掌握C++ API与游戏项目开发 (未来书库)
上QQ阅读APP看书,第一时间看更新

4.2 使用标签

游戏场景中的文字包括静态文字和动态文字。静态文字如图4-2所示,游戏场景中①号文字为“COCOS2DX”;动态文字如图4-2所示,游戏场景中的②号文字为“Hello World”。

图4-2 场景中的文字

静态文字一般是由美工使用Photoshop绘制在背景图片上,这种方式的优点是表现力丰富。例如:①号文字“COCOS2DX”中的“COCOS”、“2D”和“X”的设计风格不同,而动态文字则不能,而且静态文字无法通过程序访问,无法动态修改内容。

动态文字一般需要通过程序访问,需要动态修改内容。Cocos2d-x可以通过标签类实现。

Cocos2d-x中标签类有两个:Label和LabelAtlas。我们重点介绍Label类。

4.2.1 使用Label类

Cocos2d-x 3.x后推出了新的标签类Label,这种标签通过使用FreeTypeFreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎,它提供统一的接口来访问多种字体格式文件。——引自于百度百科http://baike.baidu.com/view/4579855.htm来使它在不同的平台上有相同的视觉效果。由于使用更快的缓存代理,它的渲染也将更加快速。Label提供了描边和阴影等特性。Label类可以创建系统字体标签、TTF字体标签和位图字体标签。

提示

系统字体标签就是当前平台系统中安装的字体,我们要确保所用字体在系统中是存在的。TTF字体TTF(TrueTypeFont)是Apple公司和Microsoft公司共同推出的字体文件格式,随着Windows的流行,已经变成最常用的一种字体文件表示方式。——引自于百度百科http://baike.baidu.com/view/1003637.htm标签是加载TTF字体文件显示文字的标签。位图字体标签加载两个文件:一个纹理图集(.png)和一个字体坐标文件(.fnt)。

Label类的类图如图4-3所示。

图4-3 Label类图

创建Label类静态create函数如下:

static Label* createWithSystemFont(const std::string & text,          //要显示的文字
     const std::string & font,                                 //系统字体名
     float fontSize,                                         //字体的大小
     const Size & dimensions = Size::ZERO,                      //在屏幕上占用的区域大小,可省略
     TextHAlignment  hAlignment = TextHAlignment::LEFT,           //文字横向对齐方式,可省略
     TextVAlignment  vAlignment = TextVAlignment::TOP)            //文字纵向对齐方式,可省略

static Label* createWithTTF(const std::string & text,
   const std::string &  fontFile,                              //字体文件
   float  fontSize,
   const Size &  dimensions = Size::ZERO,                        //可省略
   TextHAlignment       hAlignment = TextHAlignment::LEFT,          //可省略
   TextVAlignment       vAlignment = TextVAlignment::TOP            //可省略
 )   

static Label* createWithTTF(const TTFConfig& ttfConfig,
   const std::string& text,
   TextHAlignment alignment = TextHAlignment::LEFT,
   int maxLineWidth = 0
 )

static Label* createWithBMFont(const std::string& bmfontFilePath,     //位图字体文件
   const std::string&  text,        
   const TextHAlignment& alignment = TextHAlignment::LEFT,          //可省略
   int  maxLineWidth = 0,                                      //可省略
   const Vec2&  imageOffset = Vec2::ZERO                          //可省略
 )

其中createWithSystemFont是创建系统字体标签对象,createWithTTF是创建TTF字体标签对象,createWithBMFont是创建位图字体标签对象。

下面我们通过一个实例介绍它们的使用,这个实例如图4-4所示。

图4-4 Label类实例

下面HelloWorldScene.cpp中的init函数如下:

bool HelloWorld::init()
{
  if ( !Layer::init() )
  {
    return false;
  }

  Size visibleSize = Director::getInstance()->getVisibleSize();
  Vec2 origin = Director::getInstance()->getVisibleOrigin();
  auto closeItem = MenuItemImage::create(
                        "CloseNormal.png",
                        "CloseSelected.png",
                 CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

 closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,origin.y + closeItem->getContentSize().height/2));

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

auto label1 = Label::createWithSystemFont("Hello World1", "Arial", 36);            ①
label1->setPosition(Vec2(origin.x + visibleSize.width/2,
   origin.y + visibleSize.height - 100));
this->addChild(label1, 1);

auto label2 = Label::createWithTTF("Hello World2", "fonts/Marker Felt.ttf", 36);    ②
label2->setPosition(Vec2(origin.x + visibleSize.width/2,
   origin.y + visibleSize.height - 200));
this->addChild(label2, 1);

auto label3 = Label::createWithBMFont("fonts/BMFont.fnt", "Hello World3");          ③
label3->setPosition(Vec2(origin.x + visibleSize.width/2,
   origin.y + visibleSize.height - 300));
this->addChild(label3, 1);

TTFConfig ttfConfig("fonts/Marker Felt.ttf",
   36,
   GlyphCollection::DYNAMIC);                                                  ④
auto label4 = Label::createWithTTF(ttfConfig, "Hello World4");                     ⑤
label4->setPosition(Vec2(origin.x + visibleSize.width/2,
   origin.y + visibleSize.height - 400));
this->addChild(label4 , 1);

ttfConfig.outlineSize = 4;                                                     ⑥
auto label5 = Label::createWithTTF(ttfConfig, "Hello World5");                      ⑦
label5->setPosition(Vec2(origin.x + visibleSize.width/2,
   origin.y + visibleSize.height - 500));
label5->enableShadow(Color4B(255,255,255,128), Size(4, -4));                         ⑧
label5->setColor(Color3B::RED);                                                 ⑨
this->addChild(label5, 1);

return true;
}

在上面的代码中,第①行代码是通过createWithSystemFont函数创建Label对象,第②行代码是通过createWithTTF创建TTF字体标签对象,第③行代码createWithBMFont是创建位图字体标签对象。

第④行代码TTFConfig ttfConfig("fonts/Marker Felt.ttf", 36, GlyphCollection::DYNAMIC)是创建一个TTFConfig结构体变量,TTFConfig结构体的定义如下:

_ttfConfig(const char* filePath = "",                           //字体文件路径
  int  size = 12,                                      //字体大小
  const GlyphCollection& glyphCollection = GlyphCollection::DYNAMIC,  //字体库类型
  const char * customGlyphCollection = nullptr,                 //自定义字体库
  bool useDistanceField = false,                           //开启字段距离字体开关
  int outline = 0                                    //字体描边
)

第⑤行代码Label::createWithTTF(ttfConfig, "Hello World4")是通过指定TTFConfig创建TTF字体标签。第⑥行代码ttfConfig.outlineSize = 4设置TTFConfig的描边字段。第⑦行代码Label::createWithTTF(ttfConfig, "Hello World5")是重新创建TTF字体标签。

第⑧行代码label5->enableShadow(Color4B(255,255,255,128), Size(4, -4))是设置标签的阴影效果。第⑨行代码label5->setColor(Color3B::RED)是设置标签的颜色。

4.2.2 标签中文无法正常显示的问题

我们在Windows下使用Visual Studio开发游戏时,使用的标签中包含中文时会出现乱码或无法显示,如图4-5所示,而我们希望显示的中文如图4-6所示。

图4-5 标签出现乱码或无法显示

图4-6 标签显示中文

HelloWorldScene.cpp中init函数如下:

bool HelloWorld::init()
{
  if ( !Layer::init() )
  {
    return false;
  }

  Size visibleSize = Director::getInstance()->getVisibleSize();
  Vec2 origin = Director::getInstance()->getVisibleOrigin();
  auto closeItem = MenuItemImage::create(
    "CloseNormal.png",
    "CloseSelected.png",
    CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

  closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
    origin.y + closeItem->getContentSize().height/2));


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

  auto label1 = Label::createWithSystemFont("中国1", "Arial", 30);   
  label1->setPosition(Vec2(origin.x + visibleSize.width / 2,
    origin.y + visibleSize.height/2 + 50));
  this->addChild(label1, 1);

  auto label2 = Label::createWithBMFont("fonts/bitmapFontChinese.fnt", "中国2");  
  label2->setPosition(Vec2(origin.x + visibleSize.width/2,
    origin.y + visibleSize.height/2));
  this->addChild(label2, 1);

  TTFConfig ttfConfig("fonts/STLITI.ttf", 36, GlyphCollection::DYNAMIC);
  auto labe3 = Label::createWithTTF(ttfConfig,"您好,美好的一天啊",
                     TextHAlignment::CENTER,
                     visibleSize.width);
  labe3->setPosition(Vec2(origin.x + visibleSize.width/2,
    origin.y + visibleSize.height/2 - 50));
  this->addChild(labe3, 1);

  return true;
}

上述代码出现乱码或无法显示的原因与4.1.3节类似,由于在Windows中文环境下使用Visual Studio创建的源程序文件是采用GBK编码。而在Android和iOS平台,由于也采用UTF-8编码,那么上面的问题就不会出现。

解决方法很简单,我们只需要把HelloWorldScene.cpp文件另存为UTF-8就可以了,用记事本等文本编辑工具打开然后另存为UTF-8就可以了,或者在Visual Studio工具中选择“菜单文件→高级保存”选项,在弹出如图4-7所示的对话框,选择编码为Unicode(UTF-8无签名),然后单击“确定”按钮保存。

图4-7 高级保存选项

注意

不能保存为Unicode(UTF-8带签名)。