Cocos2d-x - UI components

  • Tutorial

From translator


Welcome back! We continue our translation cycle for Cocos2d-x documentation . By tradition, I should leave a link to the previous article here:
Cocos2d-x - Processing Actions

Let's Continue!

UI components


Having looked at the many applications that you used, I bet that you will find UI widgets there, even without any idea about them. Each application most likely uses several widgets. What does UI mean? What do UI widgets do? Oh so many questions!

Widgets


UI is an abbreviation for user interface. That is all that is on the screen. This includes elements such as labels , buttons , menu items, and more. Cocos2d-x provides a set of widgets to easily add these controls to your projects. This may sound trivial, but in the process of creating a core class, such as Label , a large number of operations are performed. Can you imagine that you need to write your own set of widgets? Do not worry, all this is quite feasible!

Label


Cocos2d-x provides a Label object that can create labels using a true type , bitmap, or system font. This single class implements all the labels in the application.

Label BMFont


BMFont is a type of label that uses a bitmap font. Symbols in a raster font consist of a matrix of points . It is very fast and easy to use, but not scalable, as it requires a separate font for each character size. Each character in the inscription is a separate sprite. Thanks to this method, each character can be rotated, scaled or colored. They can have different reference points or other parameters.

Creating BMFont captions requires two files: a .fnt file and a graphic representation of each character in .png format. If you use tools like Glyph Designer these files will be created automatically. Creating a Label Object UsingBMFont :

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

image

All characters specified in the parameter string must be found in the provided .fnt file, otherwise they will not be displayed. If you display an inscription and there are no characters in it, make sure that they exist in your .fnt file.

LabelTTF


True Type Fonts is different from the bitmap fonts that we learned about above. When using TTF , the font outline itself is rendered. This is convenient since you no longer need to have separate font files for each size and color that you might want to use. Creating a label using TTF is simple. To create, you need to specify the name of the .ttf file, a line of text and size. Unlike BMFont , TTF can display resized without having to have separate font files. An example of using TTF :

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

image

Although it is more flexible than a birmap font, TTF is slower to display, and changing parameters such as size is an expensive operation.

If you need multiple Label objects that use TTF and have the same parameters, you can create TTFConfig to manage them. TTFConfig allows you to set common properties that all your labels will have. You can think of it as a recipe where all your Label objects will use the same ingredients.

You can create a TTFConfig object in the following way:

// создаем TTFConfig файл для всех надписей
TTFConfig labelConfig;
labelConfig.fontFilePath = "myFont.ttf";
labelConfig.fontSize = 16;
labelConfig.glyphs = GlyphCollection::DYNAMIC;
labelConfig.outlineSize = 0;
labelConfig.customGlyphs = nullptr;
labelConfig.distanceFieldEnabled = false;
// создаем TTF Label с помощью TTFConfig файла
auto myLabel = Label::createWithTTF(labelConfig, "My Label Text");

image

TTFConfig can even be used to display Chinese, Japanese, and Korean characters.

Label SystemFont


SystemFont is a type of label that uses a standard system font and its size. It is understood that the properties of this font cannot be changed. Remember, the system font is the system rule . Creating a label with SystemFont:

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

image

Label effects


After you have Label objects on the screen, you may want to make them a little prettier. They may look flat or too simple. Fortunately, you do not need to create your own fonts for this. Not all Label objects support all effects. These include shadows , outlines, and highlights . You can add one or more effects without difficulty.

Label with shadow effect:

auto myLabel = Label::createWithTTF("myFont.ttf", "My Label Text", 16);
// Эффекты теней поддерживают все типы Label
myLabel->enableShadow();

image

Label with contour effect:

auto myLabel = Label::createWithTTF("myFont.ttf", "My Label Text", 16);
// Эффекты контура только для TTF, указываем желаемый цвет контура
myLabel->enableOutline(Color4B::WHITE, 1));

image

Glitter Label:

auto myLabel = Label::createWithTTF("myFont.ttf", "My Label Text", 16);
// Эффекты бликов только для TTF, указываем желаемый цвет блика
myLabel->enableGlow(Color4B::YELLOW);

image

Menu and its elements


We are all familiar with the idea of ​​the menu. We see them in every application used. In your game, you probably would use Menu objects to navigate in the game settings. Menus quite often contain buttons like Play, Quit, Settings, or About, but may also contain other objects. The Menu object is a special type of node. You can create an empty Menu object as a place for your items:

auto myMenu = Menu::create();

As described above, Play, Quit, Settings, and About are your menu items. A menu without elements forms a small scene. Cocos2d-x offers various ways to create your menu items, including the use of labels or preset images. Menu items, as a rule, have two possible states, normal ( normal ) and active ( selected ). When you click or click on a menu item, a function call is triggered. Imagine this is a chain reaction. You click on a menu item and the code you set is run. A menu can have either one or many elements.

// создание меню с одним элементом
// создание элемента меню из указанного изображения
auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
auto menu = Menu::create(closeItem, NULL);
this->addChild(menu, 1);

A menu can also be created by using a vector of MenuItem objects:

// создание меню при помощи вектора элементов
Vector MenuItems;
auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
MenuItems.pushBack(closeItem);
/* повторяется столько раз, сколько необходимо, для каждого элемента*/
auto menu = Menu::createWithArray(MenuItems);
this->addChild(menu, 1);

A sample menu that consists of MenuItem objects using labels:

image

Lambda functions in MenuItem


Above, we talked about the fact that when you click on a menu item, a callback function is triggered . C ++ 11 offers lamda functions. Consequently, Cocos2d-x takes full advantage of them! A Lambda function is a function that you write inside your source code. Lambda functions are calculated at runtime, and not at compile time.

Simple lambda function:

// создание простой lambda функции
auto func = [] () { cout << "Hello World"; };
// теперь вызовете ее где нибудь в коде
func();

Using the lambda function in MenuItem:

auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
[&](Ref* sender){
    // ваш код
});


Button


I doubt that we need to talk about buttons for a long time. We all know them, such as the things we click on to trigger an event in your game. You can use the buttons to change the scene or add sprites to your game. The button captures the click event and calls the predefined callback function. Do the buttons have a normal ( normal ) and the active ( selected ) state. The appearance of the button may vary, depending on the state. Creating a button and assigning a function to it is simple:

#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);

As you can see, in the example above we specify .png images for each possible button state. The button consists of three images, which can look like this:

imageimageimage

On the screen, the button will look like this:

image

Checkbox


We are all used to filling out paper-based check boxes, such as job applications or rental agreements. You can also have these flags in your game. Perhaps you want to give the player the opportunity to make a simple choice, yes or no . You may also come across the name binary choice (1 or 0). CheckBox allows you to make this choice. There are 3 different CheckBox states : normal , selected, and disabled . Creating a CheckBox is simple:

#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 << "checkbox 1 clicked" << std::endl;
                        break;
                default:
                        break;
        }
});
this->addChild(checkbox);

As you can see in the example above, we specify .png images for each CheckBox state. These are 5 images, one for each state, plus 2 more for the flags themselves:

imageimageimageimageimage

On the screen, the CheckBox will look like this:

image

LoadingBar


Have you ever had to wait for a game to download all the necessary content. You were probably shown a strip filling up as the download progressed. Pretty much this is called progress bar , status bar or loading bar . Creating a LoadingBar:

#include "ui/CocosGUI.h"
auto loadingBar = LoadingBar::create("LoadingBarFile.png");
// указание направления загрузки
loadingBar->setDirection(LoadingBar::Direction::RIGHT);
this->addChild(loadingBar);

In the example above, a LoadingBar was created and we set the direction in which it should fill. In this case, to the right. However, you will probably need to change the percentage of load. This is easy to do:

#include "ui/CocosGUI.h"
auto loadingBar = LoadingBar::create("LoadingBarFile.png");
loadingBar->setDirection(LoadingBar::Direction::RIGHT);
// что-нибудь происходит, изменяем процент загрузки
loadingBar->setPercent(25);
// происходит еще кое-что, изменяем процент загрузки
loadingBar->setPercent(35);
this->addChild(loadingBar);

As you can see in this example, the .png image is set as the texture of the LoadingBar:

image

On the LoadingBar screen, it might look like this:

image

Scrollview


Suppose you have a menu full of options for a player. You cannot put them all in one column on the screen. Will you get rid of them? Not! You are using ScrollView . You can create a ScrollView to navigate horizontally or vertically. To create a ScrollView you need:

#include "ui/CocosGUI.h"
auto scrollView = cocos2d::ui::ScrollView::create();

We created ScrollView . By default, ScrollView is vertical. You can also scroll horizontally or in both directions. Example:

#include "ui/CocosGUI.h"
// создаем вертикальный ScrollView 
auto scrollView = cocos2d::ui::ScrollView::create();
// то же самое, что было выше, но более детально
//
auto scrollView = cocos2d::ui::ScrollView::create();
scrollView->setDirection(cocos2d::ui::ScrollView::Direction::VERTICAL);

Slider


Sometimes it is necessary to slightly change a value. Perhaps you have a character, and you want to give the player the opportunity to adjust the attack power of enemies. Slider allows you to set the value by moving the indicator. How to create a Slider :

#include "ui/CocosGUI.h"
auto slider = Slider::create();
slider->loadBarTexture("Slider_Back.png"); // как будет выглядеть Slider
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);

As you may have noticed, we specify .png images for each possible state of the slider. Slider includes 5 images that may look like this:

imageimageimageimageimage

On the screen it looks like this:

image

Textfield


What if you want to give the player the opportunity to type the name of the main character? Where would you do it? Of course in the text box. TextField is used to insert text. It supports touch input, focus, percentage positioning and percentage size. Creating a TextField:

#include "ui/CocosGUI.h"
auto textField = TextField::create("","Arial",30);
textField->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type){
                std::cout << "editing a TextField" << std::endl;
});
this->addChild(textField);

This example creates a TextField and sets the callback function.

TextField objects are versatile and can meet all your needs. Do you want the user to enter a secret password? Do you need to limit the number of characters that a user can enter? All of this is built into TextField and more! Let's take a look at an example:

#include "ui/CocosGUI.h"
auto textField = TextField::create("","Arial",30);
// делаем этот TextField предназначенным для ввода пароля
textField->setPasswordEnabled(true);
// задаем максимальное количество символов, которое может ввести пользователь
textField->setMaxLength(10);
textField->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type){
                std::cout << "editing a TextField" << std::endl;
});
this->addChild(textField);

On the screen it looks like this:

image

When you edit TextField, an on-screen keyboard appears:

image

Next article: Cocos2d-x - Scenes and special types of nodes

Also popular now: