Часто в играх очень важным является передача информации игроку
используя HUD (навигационный дисплей). Часто сдесь отображается здоровье
игрока, количество боеприпасов, или сообщение о текущей задаче. Обычно
HUD содержит несколько различных
элементов. Сдесь будет описано как создавать эти елементы и использовать их для отображения информации пользователю.
Введение
HUD элементы используют библиотеку
VGUI2 для рендеринга
их состояния. Это позволяет им не только выглядеть и быть похожими на
остальные VGUI элементам в игре, но также позволяет им использовать
скриптовые, анимированные компоненты, значительно увеличивая их
визуальное качество. Это требует наличие двух компонент на стороне
клиента: объявление в коде и скриптовые файлы которые доступны клиенту
для выполнения, скрипты - это файлы не входящие в код клиента.
Классы HUD элементов наследуются от базового класса
CHudElement.
Этот базовый класс работает с обновлением, отрисовкой и скрытием HUD
элементов основанных на определенном игровом состоянии (HUD элемент
может быть установлен или исчезнуть когда игрок умирает). Этот файл
также интерпретирует файл
HudLayout.res в папке
/scripts вашего мода для определения позиций и поведений элементов. Большинсво элементов наследуются от базового класса
vgui::Panel.
Он предоставляет им примитивные панели на которых можно отрисовывать
текст, формы или текстуры. Для более детальной информации по классу
vgui::Panel, обратитесь к документации по
VGUI2 предоставленной в данном SDK.
HUD Сообщения
Элементы используют простую систему для захвата сообщений отправленных
из сервера. HUD элементы объявляют callback-функцию и связывают с ней
соответствующее сообщение. Как только сообщение получено,
callback-функция обычно читает какоето количество информации из
сообщения и отображают или обновляют их визуальное состояние. К примеру -
сообщение
Damage отсылается сервером когда игрок получает
повреждение. Сообщение кодируется количеством повреждения и
расположением. HUD элемент
Health получает сообщение и
проигрывает анимации также выдавая ее числовое значение для отображения
нового количества здоровья игрока.
Обработчик сообщения объявляется в HUD элементе следующим макросом:
DECLARE_HUD_MESSAGE( CMyHUDClass, MyHUDMessage );
Первый параметр указываает класс объявляющий обработчик сообщения,
второй это данное сообщение. Макрос приводит имя сообщения к функции
которая должна быть описана в классе HUD элемента. Поэтому, создаваемая
callback-функция должна быть такой:
void MsgFunc_MyHUDMessage( bf_read &msg );
Прототип и тело функции должны содержать данное объявление. Класс
bf_read
- это буффер данных с различными методами запросов. Он используется для
передачи неформатированных данных между сервером и клиентом. Сервер
использует
класс bf_write для передачи данных.
HUD элемент должен также включать определение макроса
HOOK_HUD_MESSAGE, обычно вызываемый функцией
Init() HUD элемента. Продолжая наш пример описанный выше, объявление будет такое:
HOOK_HUD_MESSAGE( MyHUDMessage );
Данный макрос регистрирует сообщение и связывает его с callback-функцией
описанной раньше. Ошибочное включение данного объявления приведет к
ошибке когда сервером будет отослано сообщение.
Отправка сообщения из сервера
Для правильного приема сообщений клиентом, они должны быть объявлены и отправлены сервером. Это совершает функция
Register() в синглетон-классе
usermessages.
void CUserMessages::Register( const char *name, int size )
Эта функция создает описание сообщения и удерживает его на протяжении
существования сессии. Когда сообщение отправляется, имя (name) указанное
сдесь использется для идентификации сообщения как такого что было
отправлено клиенту.
name
Текстовый идентификатор совпадающий с идентификатором описанным с помощью DECLARE_HUD_MESSAGE в HUD элементе.
size
Размер в байтах сообщения планируемого к отправке.
(Примечание: Значение -1 подразумавается как размер переменной неизвестный).
все сообщения должны быть объявлены в глобальной функции
RegisterUserMessages(). Эта функция вызывается во время создания синглетон-класса
usermessage. Не объявленные сообщения не будут удачно приняты клиентом и могут вызвать ошибку в случае попытки такой отправки.
Если были соблюдены все шаги, HUD элемент должен иметь работающую
инфраструктуру для отправки и приема сообщений от сервера к клиенту. Для
отправки сообщения, используются функции
UserMessageBegin(),
MessageEnd(), и другие поддерживаемые макросы описанные ниже.
Функция UserMessageBegin() описана так:
void UserMessageBegin( IRecipientFilter& filter, const char
*messagename )
Эта функция создает пользовательское сообщение данного типа по имени
(name), и приготавливается к получению данных от пользователя. Фильтр
(filter) может быть любого типа IRecipientFilter (CSingleUserRecipientFilter, CBroadcastRecipientFilter, и т.д.) как описано в ../dlls/recipientfilter.h.
filter
Фильтр отправки сообщения правильным получателям.
messagename
Идентификатор для данного сообщения (какой был зарегистрирован до этого).
Следующие макросы предоставляют функциональность для записи данных в
поток отправляемый клиенту. Они должны быть приняты и обработаны в
порядке отправления. Макросы записываются так:
...
WRITE_BYTE( m_uchMyByte );
WRITE_VEC3COORD( m_vecMyOrigin );
WRITE_BOOL( m_bMyState );
...
Ниже приводится описание всех доступных макросов для отправки данных в поток:
WRITE_BYTE - Один байт
WRITE_CHAR - Один символ
WRITE_SHORT - Одно целое (short)
WRITE_WORD - Одно слово (двойной байт)
WRITE_LONG - Одно длинное целое
WRITE_FLOAT - Одно с плавающей запятой
WRITE_ANGLE - Беззнаковй 8-битный угол
WRITE_COORD - Сжатое значение координат
WRITE_VEC3COORD - Сжатое значение координат из Vector типа
WRITE_VEC3NORMAL - Сжатое нормальное значение из Vector типа
WRITE_ANGLES - Сжатое угловое значение из Vector типа
WRITE_STRING - Строка символов
WRITE_ENTITY - Индекс энтити (целое, short)
WRITE_BOOL - Один бит (булевое значение)
WRITE_UBITLONG - Значение беззнаковый длинный бит
WRITE_SBITLONG - Значение знаковый длинный бит
WRITE_BITS - Число битовых значений, которое передается как параметр
За
WRITE_ макросом, сообщение должно быть завершено функцией
MessageEnd().
Получение сообщения клиентом
Как только сообщение было отправлено сервером, клиент принимает его
через callback -функцию закрепленной за этим сообщением. Принимающей
callback-функции передается переменная класса
bf_read
которая содержит данные полученные из сервера. Класс содержит
специальные функции для чтения форматированных данных из потока. И опять
же, данные должны быть считаны в том порядке в котором отправлялись.
Теперь, когда данные отправлены и получены между клиентом и сервером, функции отрисовки (как описано в документе по
VGUI2) могут быть использованы для отрисовки любой информации которая будет нужна на основании полученных данных.
Пример кода
Пример HUD элемента может быть найден в следующих файлах, поставляемых с примером приложения:
../cl_dll/sdk/sdk_hud_message.cpp
../dlls/sdk/sdk_env_message.cpp
../game_shared/sdk/sdk_usermessages.cpp