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,这种标签通过使用FreeType来使它在不同的平台上有相同的视觉效果。由于使用更快的缓存代理,它的渲染也将更加快速。Label提供了描边和阴影等特性。Label类可以创建系统字体标签、TTF字体标签和位图字体标签。
提示
系统字体标签就是当前平台系统中安装的字体,我们要确保所用字体在系统中是存在的。TTF字体标签是加载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带签名)。