Войти
K5EngineСтатьи

Система событий

Автор:

Небольшая статья про систему событий движка.

Введение.

В данной статье рассматривается система событий движка, классы, которые в неё входят а так же некоторые приёмы и примеры обработки событий.

Как работать с системой событий.

Для работы логики игры нужно как то реагировать на движение мышки, нажатия на клавиши клавиатуры, таймер и сообщения системы.
Для этого предназначена система обработки событий. Она состоит из трёх компонентов: TDevice, структура с описанием события и очередь событий.
TDevice ловит события системы, формирует их описание в класс TEvent и помещает его в очередь событий TEventDeque.
Далее надо уже в ручную извлечь и обработать эти события.
Для начала надо создать событийную очередь — TEventDeque и передать устройству указатель на неё:

TEventDeque EventDeque;
Device.SetEventDeque(&EventDeque);
В очередь за один проход цикла приложения попадают события, которые произошли с момента последнего рисования сцены.
Для того, что бы TDevice обработал и записал в очередь события, нужно вызвать метод ProcessEvent().
После этого нужно извлечь каждое событие из очереди и обработать его. Код будет выглядеть примерно так:
Device.ProcessEvent();

while(EventDeque.IsNotEmpty()){
  TEvent Event(EventDeque.Pop());

  switch(Event.Type){
    case EN_TIMER:{}break;
    case EN_MOUSE:{}break;
    default:break;
  }
}
Типы и подтипы событий описаны в enum-типе enEventTypes, который находится в заголовочном файле [K5Engine][Core][EventSystem][enum_EventTypes.h].
По поводу организации описаний типов событий в  enEventTypes: в задании подтипов событий используется запись такого вида:
например EN_SYSTEM в перечислении равна 1, тогда события, которые относятся к системным,
в своём значении будут начинаться с единицы: EN_QUIT = 100, EN_ACTIVATE = 102, EN_DEACTIVATE = 103 и так далее.

Для того, что бы узнать, какой тип события произошёл, надо проверить значение переменной Type у  TEvent:
EN_NONE — нет события, данный параметр не должен появляться у события, извлечённого из очереди, но он по умолчанию присваивается новому экземпляру  Tevent.
EN_SYSTEM  — системное событие, такое как потеря фокуса, изменения размера окна, закрытие окна.
EN_KEYBOARD — события клавиатуры: нажатия на клавиши.
EN_MOUSE — события мыши: движение, клики, прокрутка колёсика.
EN_TIMER — событие тика таймера, время указывается в секундах и в миллисекундах.
EN_USER — события пользователя, используется если надо поместить в очередь какое нибудь собственное событие. Однако такая потребность возникает крайне редко,
да и использовать её нужно аккуратно.

В зависимости от типа произошедшего события нужно выполнить те или иные действия.  TEvent имеет вложенные структуры для каждого типа события:
TSystemEvent System — параметры системного события.
TKeyboardEvent Keyboard — параметры события клавиатуры.
TMouseEvent Mouse — параметры события мыши.
TTimerEvent Timer — таймер.

Структура TSystemEvent

Структура описывает системные события, имеет всего три параметра:
enEventTypes Type — тип произошедшего системного события;
int  WindowWidth — новое значение ширины окна при событии WINDOWRESIZE;
int  WindowHeight — новое значение высоты окна при событии WINDOWRESIZE;
Параметр Type может принимать такие значения:
EN_QUIT — закрытие окна приложения.
EN_WINDOWRESIZE — изменение размера окна.
EN_ACTIVATE — окно стало активно, появился фокус.
EN_DEACTIVATE — окно стало не активно, пропал фокус.
EN_PAINT — перерисовка окна, выполняется при не активном окне.
EN_MINIMIZE — событие сворачивания окна.
EN_RESTORE — событие восстановления окна, приходит при разворачивании окна.
EN_DEVICELOST — потеря устройства, событие актуально только для TWinApiDX8Device.
EN_DEVICERESTORE - восстановление устройства, событие актуально только для TWinApiDX8Device.
EN_DISPLAYCHANGE — событие приходит, когда изменяется разрешение экрана.

Структура TKeyboardEvent

Структура описывает событие нажатия или отпускание кнопки на клавиатуре.имеет такие параметры:
enEventTypes Type — тип клавиатурного события. Может принимать такие значения:
EN_KEYDOWN — кнопка нажата
EN_KEYUP — кнопка отжата
enEventTypes Key — вируальный код клавиши, которая нажата. Список большой и него нет смысла здесь приводить.
Коды начинаются с префикса EN_KEY_ и буквы, цифры или сокращения  клавиши на английском языке, например: EN_KEY_A, EN_KEY_K, EN_KEY_9,  EN_KEY_MINUS.
Весь список можно найти в ранее упоминаемом enum_EventTypes.h.
wchar_t Symbol — реальный символ, который был введён с клавиатуры. Символ приходит только при событии  EN_KEYDOWN.

Структура TMouseEvent

Структура описывает событие мыши — движение, клики, вращение колёсика. Она имеет такие параметры:
enEventTypes Type — тип события мыши. Может принимать такие значения:
EN_MOUSEMOTION — движение мыши.
EN_MOUSEBUTTONDOWN — кнопка мыши нажата.
EN_MOUSEBUTTONUP — кнопка мыши отпущена.
EN_MOUSEWINDOWOUT — приходит, когда курсор мыши покидает границы окна.
EN_MOUSEWINDOWIN — приходит, когда курсор мыши возвращается в границы окна.
EN_MOUSEWHEELUP — вращение колёсика мыши вверх.
EN_MOUSEWHEELDOWN — вращение колёсика мыши вниз.
enEventTypes Button — кнопка мыши, которая была нажата, значение задаётся при  EN_MOUSEBUTTONUP и EN_MOUSEBUTTONDOWN и принимает такие значения:
EN_MOUSEBUTTONLEFT — левая кнопка.
EN_MOUSEBUTTONMIDDLE — кнопка по середине.
EN_MOUSEBUTTONRIGHT — правая кнопка.
А так же координаты курсора мыши X и Y, которые приходят при движении мыши и при нажатии на кнопки.

Структура TTimerEvent

Событие таймера, на нём строится работа всей игровой логики — передвижение объектов с определённой скоростью, анимации, разнообразные игровые действия. TtimerEvent имеет два параметра: Sec, Ms. Sec — сколько прошло секунд с последней отрисовки сцены,  Ms — сколько прошло миллисекунд.
Можно использовать любой по своему усмотрению. Два параметра времени введено так как иногда требуется считать в секундах а иногда в миллисекундах,
при этом несколько не удобно постоянно переводить из одного представления времени в другое.

Параметры TDevice, влияющие на генерацию событий.

У устройства TDevice есть метод для установки минимального времени генерации события таймера — SetTimerEventDelay(const float &Val), принимает количество миллисекунд, по прошествии которых будет создано событие таймера. Наиболее оптимальные значения — 20, 25, 30 миллисекунд.
Что бы отключить данную возможность, достаточно передать 0 в данную функцию. По умолчанию метод не используется.
Так же есть метод для включения вертикальной синхронизации void SetEnableVSync(const bool &Val).
При включении синхронизации время прихода события таймера будет зависить от частоты обновления монитора.

Итог.

В данной статье рассмотрена событийная система движка, структура класса-события, работа с очередью и параметры устройства, влияющие на генерацию событий.
Пример к данной статье — урок номер четыре.

27 февраля 2012