Готовый перевод Ogre3D Basic Tutorials / Базовые туториалы Ogre3D: Basic Tutorial 5: Buffered Input
ВВЕДЕНИЕ
В этом коротком уроке вы научитесь использовать буферизованный ввод OIS, в противоположность небуферизованному, который мы использовали в прошлом уроке.
Этот урок отличается от предыдущего тем, что мы будем обрабатывать события клавиатуры и мыши сразу, как они произойдут, а не один раз за каждый кадр.
Учтите, что этот урок годится только в качестве введения в буферизованный ввод и не является полным руководством по использованию OIS.
Для более полной информации о нем обязательно прочтите статью Использование OIS (Using OIS).
С ЧЕГО НАЧАТЬ
Этот урок основан на предыдущем, но мы изменим способ, которым мы принимаем ввод пользователя.
Поскольку функциональность будет в основном та же, мы будем использовать тот же класс BaseApplication, что и в предыдущий раз.
Создайте проект для компилятора, который вы выбрали для этого проекта и добавьте следующий код:
Управление программой будет таким же, как и в прошлом уроке.
Мы переопределим методы frameRenderingQueued и createFrameListener, как и методы слушателей событий MouseListener и KeyboardListener (keyPressed(), keyReleased(), mouseMoved(), mousePressed() и mouseReleased()).
ВКРАТЦЕ О БУФЕРИЗОВАННОМ ВВОДЕ
ВВЕДЕНИЕ
В предыдущем уроке мы использовали небуферизованный ввод, то есть каждый кадр мы запрашивали состояние объектов OIS::Keyboard и OIS::Mouse, чтобы определить, какие клавиши и кнопки мыши были нажаты.
Буферизованный ввод использует интерфейс слушателей для информирования вашей программы о произошедших событиях.
Например, когда нажимается клавиша, испускается событие KeyListener::keyPressed, а когда она отпускается (больше не является нажатой) - событие KeyListener::keyReleased. Они доставляются всем зарегистрированным слушателям.
Это позволяет отслеживать моменты переключения или узнать, была ли клавиша отжата в предыдущем кадре.
OIS также поддерживает небуферизованные события джойстика через интерфейс OIS::JoystickListener, хотя мы не будем задерживаться на нем в этом уроке.
Одно важное замечание об использовании системы слушателей OIS: вы можете иметь только по одному слушателю для объектов Keyboard, Mouse или Joystick.
Это сделано для простоты (и для скорости).
Вызов функции setEventCallback (которую мы опишем ниже) несколько раз приведет к тому, что только последний зарегистрированный слушатель будет получать события.
Если вам нужно несколько объектов, получающих события от клавиатуры, мыши или джойстика, вы должны написать собственный диспатчер сообщений.
Также обязательно убедитесь, что вы вызвали Keyboard::capture и Mouse::capture (что значит захватить - прим. пер.) в методе frameRenderingQueued.
OIS не использует потоки (или магию) для определения состояний клавиатуры и мыши, поэтому вы должны определить, когда нужно захватить ввод.
ИНТЕРФЕЙС KEYLISTENER
Интерфейс OIS KeyListener предоставляет две чисто виртуальные функции.
Первая - это keyPressed (вызывается каждый раз при нажатии клавиши) и вторая - keyReleased (вызывается каждый раз при отпускании клавиши).
Этим функциям передается параметр типа KeyEvent, содержащий информацию о коде нажатой или отпущенной клавиши.
ИНТЕРФЕЙС MOUSELISTENER
Интерфейс MouseListener лишь немногим сложнее интерфейса KeyListener.
Он содержит функции, следящие за нажатием и отпусканием кнопок мыши: MouseListener::mousePressed и MouseListener::mouseReleased.
Он также содержит функцию mouseMoved, которая вызывается, когда мышь перемещается.
Каждая из этих функций получает объект MouseEvent, который содержит текущее состояние мыши в переменной "state".
Самая важная вещь в объекте MouseState, о которой стоит упомянуть, это то, что он содержит не только относительные координаты X и Y перемещения мыши (т.е. расстояние, показывающее, как далеко сместилась мышь со времени последнего вызова функции MouseListener::mouseMoved), но также и абсолютные координаты (т.е. текущее положение мыши на экране).
МОМЕНТ ИСТИНЫ: КОД
ПЕРЕМЕННЫЕ
Несколько переменных изменилось с последнего урока.
Я убрал mToggle и mMouseDown (которые больше не нужны).
И я также добавил некоторые:
Переменные mRotate, mMove и mCamNode такие же, что и в последнем уроке (хотя мы будем изменять значение mRotate, поскольку мы используем ее по-другому).
Переменная mDirection содержит информацию о том, как мы собираемся перемещать узел камеры каждый кадр.
МЕТОД CREATEFRAMELISTENER
В этом методе мы будем вызывать метод createFrameListener из класса BaseApplication и инициализировать некоторые из переменных.
Добавьте еще чуток кода в метод createFrameListener:
Объекты OIS mMouse и mKeyboard уже получены в методе createFrameListener из BaseApplication.
Здесь мы регистрируем слушателя, вызывая метод setEventCallback на объектах ввода, вот так:
И наконец, нам нужно инициализировать mDirection нулевым вектором(так мы изначально не двигались, следовательно и направления нет):
СВЯЗЫВАНИЕ КОМБИНАЦИЙ КЛАВИШ С КОМАНДАМИ
Прежде, чем двигаться дальше, мы должны связать клавишу Escape с действием выхода из программы (не вечно же любоваться на свое творение).
Найдите метод BasicTutorial05::keyPressed.
Этот метод вызывается объектом KeyEvent, каждый раз когда клавиша на клавиатуре нажимается.
Мы можем получить код нажатой клавиши (KC_*) из переменной "key" объекта.
С помощью конструкции switch на этом значении мы определим обработчики для всех клавиш, используемых в приложении.
Найдите метод keyPressed и замените его содержимое на этот код:
Также надо добавить следующий код в функцию frameRenderingQueued для того чтобы приложение реагировало на нажатия клавиш.
Это гарантирует что программа завершится когда значение переменной mShutDown станет равно true (ее значение переключится нажатием escape, как вы можете видеть в коде выше).
mKeyboard->capture() и mMouse->capture() гарантируют, что и клавиатура, и мышь захвачены нашим приложением.
И наконец mTrayMgr->frameRenderingQueued(evt) гарантирует то что наш трей будет корректно отрендерен.
Убедитесь в том что ваше приложение компилируется и запускается перед тем как продолжать дальше.
Сейчас нам надо добавить обработку других клавиш в наш switch.
Первое, что мы сделаем, это позволим пользователю переключатся между областями просмотра нажимая клавиши 1 и 2.
Код для этого (который необходимо добавить в оператор switch) тот же самый, что и в предыдущем уроке, исключая тот момент, что мы больше не работаем с переменной mToggle:
Как вы сами видите, это гораздо понятнее, чем работать с временной переменной для отслеживания момента нажатия.
Следующее что мы добавим, это управление передвижением с клавиатуры.
Каждый раз когда пользователь нажимает клавишу которая отвечает за движение, мы будем прибавлять или убавлять к значению mMove (в зависимости от направления) значение корректной ориентации в векторе.
Теперь нам необходимо при отпускании клавиши "отменить" изменение mDirection, чтобы остановить перемещение.
Найдите метод keyReleased и добавьте в него следующий код:
Теперь, когда мы имеем mDirection, обновляемую на основе ввода с клавиатуры, нам нужно произвести фактическое перемещение.
Этот код такой же, как в предыдущем уроке, исключая то, что мы двигаем узел камеры вместо узла ниндзя, так что добавим нижеследующее в функцию frameRenderingQueued:
Скомпилируем и запустим приложение.
И вот вы реализовали движение при помощи клавиш, используя буферизованный ввод! Поздравьте себя, а мы переходим к следующей части.
СВЯЗЫВАНИЕ КОМАНД С МЫШЬЮ
Теперь, когда мы завершили связывание команд с клавишами, нам нужно поработать над тем, чтобы заставить мышь работать.
Мы начнем с включения и выключения света левой кнопкой мыши.
Найдите функцию mousePressed и взгляните на параметры.
Вместе с OIS у нас есть доступ как к MouseEvent, так и к MouseButtonID.
Используя значение MouseButtonID, мы можем определить, какая кнопка была нажата.
Замените код функции mousePressed следующим:
Скомпилируйте и запустите приложение.
Вуаля! Теперь, когда это работает, единственной вещью, которую нам осталось сделать, это связать правую кнопку мыши с режимом осмотра мышью.
Каждый раз, когда мышь двигается, мы будем проверять состояние правой кнопки.
Если она нажата, мы повернем камеру, основываясь на относительном перемещении мыши.
Мы можем получить доступ к относительному перемещению мыши из объекта MouseEvent, переданного в эту функцию.
Она содержат переменную "state"(состояние), которая содержит MouseState (которая в основном содержит подробную информации о мыши).
MouseState::buttonDown сообщит, нажата или нет определенная кнопка мыши, и переменный "X" и "Y" сообщат нам об относительном перемещении мыши.
Найдите функцию mouseMoved и замените код в ней следующим:
Скомпилируйте и запустите приложение и камера будет действовать в режиме свободного обзора, пока зажата правая кнопка мыши.
ДРУГИЕ СИСТЕМЫ ВВОДА
Система OIS в основном очень хороша и должна вас устраивать при достижении большинства целей, которые вы ставили перед своим приложением.
С учетом сказанного, существуют альтернативы если вы пожелаете использовать что-то другое.
Некоторые оконные системы могут быть тем, что вы ищите, такие, как wxWidgets, которую люди с успехом интегрировали с Ogre.
Вы можете использовать стандартную систему сообщений Windows или один из многих GUI-инструментариев под Linux для обработки ввода, если вы не возражаете против того, что ваше приложение станет зависеть от платформы (вы в своем уме?!).
Вы также можете попробовать SDL (Simple DirectMedia Layer - библиотека для работы с мультимедиа), которая предоставляет не только кроссплатформенную оконую систему и систему ввода, но также ввод с джойстика/геймпада.
Хотя я и не могу дать вам рекомендации по установке wx/gtk/qt/других вместе с Ogre (поскольку я никогда раньше это не делал), у меня много раз хорошо получалось успешно состыковать функции ввода из SDL для джойстика/геймпада для работы с Ogre.
Чтобы начать работать с джойстиком системы SDL, оберните код инициализации приложения вызовами SDL_Init и SDL_Quit (это можно сделать в функции main или, возможно, в объекте вашего приложения):
Для настройки джойстика вызовите SDL_JoystickOpen с номером джойстика (вы можете указать несколько джойстиков, вызвав функцию с аргументами 0, 1, 2,...)
Если SDL_JoystickOpen вернёт NULL, значит возникла проблема открытия джойстика.
Это почти всегда означает, что джойстик, который вы запросили, не существует.
Используейте SDL_NumJoysticks, чтобы узнать, сколько джойстиков подключено к вашей системе.
Вы также должны закрыть джойстик после того, как закончили с ним работать:
Для использования джойстика, вызовите методы SDL_JoystickGetButton и SDL_JoystickGetAxis.
Я лично использовал контроллер playstation2, поэтому у меня было четыре оси и двенадцать кнопок с которыми я игрался.
Это мой код перемещения:
mTrans затем передается в метод SceneNode::translate камеры, xRot - в метод SceneNode::yaw, а yRot - в метод SceneNode::pitch.
Отмететим, что параметр SDL_JoystickGetAxis возвращает значение между -32767 и 32767, поэтому я отмасшатбировал его так, чтобы оно было между -1 и 1.
Это должно помочь вам начать использовать функции SDL для потокового ввода с джойстика.
Если вы ищете дополнительную информацию в этой области, то лучшей документаций будет, посмотреть на заголовочный файл SDL джойстика .
Вам также следует обратиться к стандартной документации по SDL, если вы начали серьезно использовать его в вашем приложении.
Переведено на Нотабеноиде
http://notabenoid.org/book/19615/64003
Переводчики: Mingun, wuffur, alexx_x, proVIDec
chmel7
Настройки
Готово:
