Готовый перевод CEGUI In Practice / CEGUI на практике: 6. A Game Console
Добро пожаловать!
В этом туториале мы соединим вместе знания, полученные в предыдущих главах, и создадим функциональную консоль.
Предыдущие туториалы давали нам лишь некоторые основы.
Пришло время объединить все полученные знания для создания чего-то, что действительно может понадобится в наших играх.
План
Отлично, теперь давайте взглянем на то, что мы собираемся делать.
Мы хотим вводить команды, нажимать кнопку отправки и видеть вывод консоли на экране.
Нам также нужно будет знать, когда нажат Enter, так как это распространенный вариант отправки сообщения.
Раньше мы обсуждали как перенаправлять ввод в CEGUI (CEGUI на практике - Управление вводом), так что будем считать, что вы знаете эту тему (и можете собрать приложение).
Также будем думать, что вы знаете как использовать .layout файл и именовать окна (CEGUI на практике - Применение .layout файлов).
В связи с тем, что здесь мы углубляемся в CEGUI немного больше, чем раньше, и потому что мы хотим, чтобы консоль делала много полезных вещей (таких как парсинг строк для команды /say), для реализации консоли я собираюсь создать класс.
// Конструктор
// Спрятать или отобразить консоль
// Возвращает true, если консоль видна и false, если спрятана
// Функция, которая будет загружать CEGUI окно и регистрировать обработчики событий
// Функция для регистрации наших обработчиков
// Обработка нажатия Enter
// Обработка нажатия кнопки отправки
// Парсинг текста, которого отправил пользователь
// Вывод сообщения в поле истории чата
// с белым цветом по умолчанию
// Это будет указатель на корневое окно консоли
// Это будет префикс, который мы дадим разметке
// Это будет вспомогательное число для этого класса.
Так выглядит наш класс.
Может выглядеть страшно, но не волнуйтесь, к концу урока все прояснится.
Конструктор
Я собираюсь использовать конструктор для автоматизации процесса.
Я считаю, что на практике плохо вызывать функции, которые могут выдать ошибку, в конструкторе, однако для простоты понимания я пренебрегу этим.
В конструкторе мы инициализируем парочку переменных и вызовем функцию CreateCEGUIWindow.
// Не забудьте это объявление
// Всегда полезно инициализировать указатель нулевым значением, помогает при переключении на Release сборку
Настройка окна
Теперь нам нужно настроить окно.
Мы делали это раньше в туториале про разметку, сделаем это еще раз здесь.
Мы уже говорили о том, что нужно использовать префикс, когда загружаешь .layout, чтобы избежать повторения имен, во время неоднократной загрузки одной и той же разметки.
Нам нужно разобраться с этим.
Нам нужна будет не одна консоль?
Давайте напишем функцию CreateCEGUIWindow:
// Устанавливаем локальный указатель на оконный менеджер CEGUI, просто для удобства и сокращения количества кода
// Теперь, перед тем как продолжать, давайте увеличим наше вспомогательное число, чтобы быть уверенными, что конфликтов не будет
// Мне нравится формат #_ConsoleRoot, такой я префикс и сделаю. Надо просто
// увеличить вспомогательное число и, добавив к нему строку "_", поместить их в переменную sNamePrefix.
// Теперь когда мы убедились, что с префиксом все в порядке и конфликтов с именами не будет, давайте создадим окно
// и привяжем его к указателю класса m_ConsoleWindow
// inLayoutName это имя вашего файла разметки (например "console.layout"), не забудьте переименовать inLayoutName
// Быть хорошим программистом, значит убедиться в том, что все хорошо.
// Давайте добавим наше новое окно к корневому окну GUI
// Теперь регистрация обработчиков событий (Щелчки мыши, ввод с клавиатуры и т.д.)
// Случилось что-то плохое, и окно создать не получилось. Нужно проинформировать об этом.
Отлично, теперь мы создали окно. А после того как окно было создано, мы зарегистрировали его обработчики.
Давайте взглянем на то, как их надо зарегистрировать.
Ниже приведена функция RegisterHandlers, если вы до этого читали внимательно, то она должна выглядеть знакомо.
// Хорошо теперь мы должны зарегистрировать обработчики. Выше мы говорили, нам нужно знать, когда пользователь нажал Enter, и
// когда он нажал кнопку "Отправить". Так что нам нужно зарегистрировать оба события.
// Сначала давайте зарегистрируем кнопку отправки. Имя нашей кнопки "ConsoleRoot/SendButton", но не забывайте, что мы добавили префикс
// ко всем окнам, которые загрузили. Нужно принять это к сведению.
// Если вспомните, наша кнопка была типа CEGUI::PushButton,
// и мы хотим знать о событии клика по ней (EventClicked).
// Какую функцию нужно вызвать, когда кнопка нажата? Помните, что все функции
// содержаться внутри (this) класса.
// Вызываем функцию Handle_SendButtonPressed, член класса GameConsoleWindow
// Используем (this) объект, в котором находимся
// Теперь для TextSubmitted мы зарегистрируем событие на поле ввода, на котором должен быть курсор мыши, когда
// пользователь нажмет Enter. Я не собираюсь вдаваться в подробности, потому что я думаю, что это будет слишком страшно читать, так что
// лучше просто написать. Вот вызов функции.
Последняя строчка выглядит ужасно, но помните, что если вы подключите пространство имен CEGUI, вам не понадобятся все эти префиксы CEGUI:: в коде.
Как видите регистрировать события довольно легко.
Стоит сказать, что есть больше действий, на которые можно реагировать.
Для кнопки можно также зарегистрировать:
Зависит от того, какой результат вы хотите получить, и где именно должно отразится действие.
Например, оконные элементы обычно реагируют на отпускание мыши, так как пользователь может кликнуть на объект, а потом передумать и отпустить кнопку мыши, предварительно стащив с элемента.
Обработчики
Теперь, когда мы зарегистрировали события, нам нужно написать функции, которые будут обрабатывать эти события.
Нам нужно обработать оба события: TextSubmitted и SendButton.
// Следующая строка кода в конкретном примере не нужна, но показать стоит. По сути EventArgs
// имеет ограниченное применение. Будет более полезно использовать его с другим типом событий. В данном случае WindowEventArgs
// Теперь нам нужно получить текст, который находится в поле ввода.
// Когда у нас уже есть строка, нужно послать ее в TextParser
// Сейчас, когда мы закончили с текстом, нам нужно позаботится об очистке поля ввода. Это то, чего мы ожидаем
// после нажатия Enter
Теперь вы должно быть удивлены, почему мы не распарсили текст прямо здесь?
Если пользователь нажмет Enter или кнопку отправки, текст в любом случае будет распарсен одинаково.
Так зачем писать одно и тоже дважды?
Ниже приведен код для обработки нажатия кнопки отправки.
Я знаю, только что говорил об одинаковых строках кода, и это выглядит просто поразительно также, как код для функции выше.
Но это потому что нам не нужна большая функциональность для кнопки.
Мы бы просто могли создать одну функцию для отправки текста, но что если бы мы захотели добавить звук, который бы звучал при нажатии на кнопку?
Тогда и нужны две различные функции.
Уже достаточно сказано, вот код.
Парсинг текста
Данная часть будет не о CEGUI, так как это больше техническая часть, касающаяся строк.
// Лично я люблю работать с std::string, так что я переконвертирую строку
// Убедимся, что строка не пустая
// Проверим, что первый символ - символ команды
// конвертируем символы команды в строчные
// Прикрепим наше "имя" к сообщению, которое отобразим
// нет команд, просто выводим, что написали
Фуф, довольно большая функция, да?
Функция проверяет на наличие переднего слеша и если он есть, то проверяет правильная команда введена или нет.
Осталось разобраться с функцией OutputText.
Она будет выводить текст в специальное поле, историю чата.
Теперь поработаем над этой функцией.
Вывод текста
// Установим цвет текста
Заключение
И это, леди и джентльмены, наша консоль.
До следующего раза...
Внимание! Этот перевод, возможно, ещё не готов.
Его статус: идёт перевод
Переведено на Нотабеноиде
http://notabenoid.org/book/29927/102406
Переводчики: proVIDec
Настройки
Готово:
