Cocos2d-x — UI компоненты

в 12:41, , рубрики: c++, cocos2d-x, разработка игр

От переводчика

С возвращением! Мы продолжаем свой цикл переводов документации к Cocos2d-x. По традиции я должен оставить здесь ссылку на предыдущую статью:
Cocos2d-x — Обработка действий

Продолжим!

UI компоненты

Взглянув на множество приложений, которые вы использовали, держу пари, что вы обнаружите там UI виджеты, даже не имея о них представления. Каждое приложение, скорее всего, использует несколько виджетов. Что означает UI? Что делают UI виджеты? О, так много вопросов!

Виджеты

UI — это аббревиатура, обозначающая пользовательский интерфейс. Это все, что находится на экране. Сюда входят такие элементы, как: надписи, кнопки, элементы меню и многое другое. Cocos2d-x предоставляет набор виджетов, для простого добавления этих элементов управления в ваши проекты. Это может звучать тривиально, но в процессе создания основного класса, такого как Label, выполняется большое количество операций. Может себе представить, что вам нужно написать свой собственный набор виджетов? Не волнуйтесь, все это вполне реализуемо!

Label

Cocos2d-x предоставляет Label объект, который может создавать надписи с использованием true type, bitmap или system шрифта. Этот единственный класс реализует все надписи в приложении.

Label BMFont

BMFont — это тип надписи, что использует растровый шрифт (bitmap font). Символы в растровом шрифте состоят из матрицы точек. Он очень быстрый и простой для использования, но не масштабируемый, поскольку это требует отдельного шрифта для каждого размера символов. Каждый символ в надписи — отдельный спрайт. Благодаря этому способу, каждый символ может быть повернут, масштабирован или окрашен. Они могут иметь разные опорные точки или другие параметры.

Создание BMFont надписи требует два файла: .fnt файл и графическое представление каждого символа в .png формате. Если вы используете инструменты подобные Glyph Designer эти файлы будут созданы автоматически. Создание объекта Label при помощи BMFont:

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

image

Все символы, заданные в строке-параметре, должны быть найдены в предоставленном .fnt файле, в противном случае они не будут отображаться. Если вы выводите надпись, и в ней отсутствуют символы, убедитесь что они существуют в вашем .fnt файле.

LabelTTF

True Type Fonts отличается от bitmap fonts о котором мы узнали выше. При использовании TTF рендерится сам контур шрифта. Это удобно, так как вам больше не нужно иметь отдельных файлов шрифта для каждого размера и цвета, которые вы, возможно, захотите использовать. Создать надпись с использованием TTF, просто. Для создания вам необходимо задать имя .ttf файла, строку текста и размер. В отличие от BMFont, TTF может отображать измененный размер без необходимости иметь отдельные файлы шрифта. Пример использования TTF:

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

image

Хотя он более гибкий чем birmap font, TTF медленнее отображается, а изменение таких параметров как размер — дорогостоящая операция.

Если вам нужно несколько объектов Label, использующих TTF и имеющих одинаковые параметры, вы можете создать TTFConfig для управления ими. TTFConfig позволяет вам задать общие свойства, которые будут иметь все ваши надписи. Вы можете думать об этом, как о рецепте где все ваши Label объекты будут использовать одинаковые ингредиенты.

Вы можете создать объект TTFConfig следующим путем:

// создаем 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 может даже быть использован для вывода Китайских, Японских и Корейских иероглифов.

Label SystemFont

SystemFont это тип надписи, который использует стандартный системный шрифт и его размер. Подразумевается что свойства данного шрифта не могут быть изменены. Запомните, системный шрифтсистемные правила. Создание надписи с SystemFont:

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

image

Label эффекты

После того, как у вас появились объекты Label на экране, вы можете захотеть сделать их немножко красивее. Возможно, они выглядят плоско или слишком просто. К счастью, вам не нужно создавать для этого собственные шрифты. Не все объекты Label поддерживают все эффекты. Они включают тени, контуры и блики. Вы можете добавить один или несколько эффектов без труда.

Label с эффектом теней:

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

// Эффекты теней поддерживают все типы Label
myLabel->enableShadow();

image

Label с эффектом контура:

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

// Эффекты контура только для TTF, указываем желаемый цвет контура
myLabel->enableOutline(Color4B::WHITE, 1));

image

Label с эффектом блеска:

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

// Эффекты бликов только для TTF, указываем желаемый цвет блика
myLabel->enableGlow(Color4B::YELLOW);

image

Меню и его элементы

Все мы уже знакомы с представление о меню. Мы видим их в каждом используемом приложении. В вашей игре вы, наверное, стали бы использовать объекты Menu для навигации в игровых настройках. Меню довольно часто содержат кнопки на подобие Play, Quit, Settings или About, но так же может содержать и другие объекты. Объект Menu это специальный тип узла. Вы можете создать пустой Menu объект в качестве места для ваших элементов:

auto myMenu = Menu::create();

Как было описано выше, Play, Quit, Settings и About — это ваши пункты меню. Меню без элементов образует маленькую сцену. Cocos2d-x предлагает различные способы создания ваших пунктов меню, включая использование надписей или задаваемых изображений. Элементы меню, как правило, имеют два возможных состояния, нормальное(normal) и активное(selected). Когда вы нажимаете или кликаете на элемент меню, срабатывает вызов функции. Представьте, что это цепная реакция. Вы кликаете по элементу меню и запускается заданный вами код. Меню может иметь как один, так и множество элементов.

// создание меню с одним элементом

// создание элемента меню из указанного изображения
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<MenuItem*> 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);

Образец меню, которое состоит из объектов MenuItem, использующих надписи:

image

Lambda функции в MenuItem

Выше мы говорили о том, что когда вы кликаете на элемент меню, срабатывает callback функция. C++11 предлагает lamda функции. Следовательно, Cocos2d-x использует все их преимущества! Lambda функция — это функция которую вы пишите внутри вашего исходного кода. Lambda функции просчитываются во время выполнения программы, а не во время компиляции.

Простая lambda функция:

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

// теперь вызовете ее где нибудь в коде
func();

Использование lambda функции в MenuItem:

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

Button

Я сомневаюсь, что нам необходимо долго рассказывать про кнопки. Мы все знаем их, как такие штуки, на которые мы кликаем для вызова некоторого события в вашей игре. Вы можете использовать кнопки для изменения сцены или добавления спрайтов в вашу игру. Кнопка перехватывает событие нажатия и вызывает предопределенную callback функцию. У кнопок есть нормальное(normal) и активное(selected) состояния. Вид кнопки может изменятся, в зависимости от состояния. Создать кнопку и назначить ей функцию просто:

#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 изображения для каждого возможного состояния кнопки. Кнопка состоит из трех изображений, которые могут выглядеть следующим образом:

image image image

На экране кнопка будет выглядеть так:

image

CheckBox

Мы все привыкли заполнять флажки на бумажных формах, таких как заявления на работу или договоры на аренду. Вы тоже можете иметь такие флажки в своей игре. Возможно, вы хотите дать игроку возможность сделать простой выбор, да или нет. Так же вам может встретиться название бинарный выбор (1 или 0). CheckBox позволяет сделать такой выбор. Существует 3 различных состояния CheckBox: normal, selected и disabled. Создать 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 << "checkbox 1 clicked" << std::endl;
                        break;
                default:
                        break;
        }
});

this->addChild(checkbox);

Как вы можете видеть в примере выше, мы задаем .png изображения для каждого состояния CheckBox. Это 5 изображений, по одному для каждого состояния, плюс еще 2 для самих флажков:

image image image image image

На экране CheckBox будет выглядеть вот так:

image

LoadingBar

Вам когда-нибудь приходилось ждать, пока игра загрузит весь необходимый контент. Вероятно, вам показывали полосу, заполняемую по мере прогресса загрузки. Довольно часть это называют progress bar, status bar или loading bar. Создание LoadingBar:

#include "ui/CocosGUI.h"

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

// указание направления загрузки
loadingBar->setDirection(LoadingBar::Direction::RIGHT);

this->addChild(loadingBar);

В примере выше, был создан LoadingBar и мы задали ему направление, в котором он должен заполнятся. В данном случае вправо. Однако, вам, вероятно, нужно будет изменять процент загрузки. Это сделать легко:

#include "ui/CocosGUI.h"

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

// что-нибудь происходит, изменяем процент загрузки
loadingBar->setPercent(25);

// происходит еще кое-что, изменяем процент загрузки
loadingBar->setPercent(35);

this->addChild(loadingBar);

Как вы можете видеть в этом примере заданно .png изображение в качестве текстуры LoadingBar:

image

На экране LoadingBar может выглядеть так:

image

ScrollView

Допустим, у вас есть меню, полное опций для игрока. Вы не можете поместить их всех в одну колонку на экране. Вы избавитесь от них? Нет! Вы используете ScrollView. Вы можете создать ScrollView для навигации по горизонтали или вертикали. Для создания ScrollView нужно:

#include "ui/CocosGUI.h"

auto scrollView = cocos2d::ui::ScrollView::create();

Мы создали ScrollView. По умолчанию, ScrollView располагается вертикально. Вы так же можете скролить горизонтально или в обоих направлениях. Пример:

#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

Иногда необходимо слегка изменить какое-либо значение. Возможно, у вас есть персонаж, и вы хотите дать игроку возможность настраивать силу атаки врагов. Slider позволяет задавать значение, перемещая индикатор. Как создать 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);

Как вы могли заметить, мы задаем .png изображения для каждого возможного состояния ползунка. Slider включает 5 изображений, которые могут выглядеть так:

image image image image image

На экране это выглядит следующим образом:

image

TextField

Что если вы хотите дать игроку возможность напечатать имя главного персонажа? Где бы вы это сделали? Конечно в текстовом поле. TextField используется для вставки текста. Он поддерживает сенсорный ввод, фокус, процентное позиционирование и процентный размер. Создание 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);

В этом примере создается TextField и задается callback функция.

Объекты TextField универсальны и могут соответствовать всем вашим потребностям. Вы хотите, чтобы пользователь вводил секретный пароль? Вам нужно ограничить количество символов, что может вводить пользователь? Все это встроено в TextField и даже больше! Давайте взглянем на пример:

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

На экране это выглядит так:

image

Когда вы редактируете TextField, появляется экранная клавиатура:

image

Автор: MrMysterious

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js