[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Игровые движки » IrrLicht Engine » Туториал №19: Джойстик и Мышь
Туториал №19: Джойстик и Мышь
MerGC_TeamДата: Четверг, 03.04.2014, 18:19 | Сообщение # 1
Веселый админ
Группа: Администраторы
Сообщений: 32
Статус: Оффлайн
Этот туториал построен на уроке №04 Движение в котором показано, как обрабатывать клавиатурные события в IrrLicht Engine. Здесь мы научимся обрабатывать события мыши и джойстика, если у вас подключен джойстик и имеется поддержка джойстика. В настоящее время такая поддержка встроена в Windows, Linux и SDL устройства.
Код
#ifdef _MSC_VER
// Мы определили это для того, чтобы компилятор MSVC прекратил жаловаться на ф-цию sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib")
#endif

#include < irrlicht.h >
#include "driverChoice.h"

using namespace irr;


Так же как мы делали в примере №04 Движение, мы сохраняем последние состояния мыши и первого джойстика, обновляем данные как только получаем события..
Код
class MyEventReceiver : public IEventReceiver
{
public:
         // Создаём структуру для записи состояний мыши
         struct SMouseState
         {
                 core::position2di Position;
                 bool LeftButtonDown;
                 SMouseState() : LeftButtonDown(false) { }
         } MouseState;

         // Это единственный метод, который мы должны переопределить
         virtual bool OnEvent(const SEvent& event)
         {
                 // Запомнить состояния мыши
                 if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
                 {
                         switch(event.MouseInput.Event)
                         {
                         case EMIE_LMOUSE_PRESSED_DOWN:
                    MouseState.LeftButtonDown = true;
                    break;

                         case EMIE_LMOUSE_LEFT_UP:
                    MouseState.LeftButtonDown = false;
                    break;

                         case EMIE_MOUSE_MOVED:
                    MouseState.Position.X = event.MouseInput.X;
                    MouseState.Position.Y = event.MouseInput.Y;
                    break;

                         default:
                    // Мы не будем обрабатывать колёсико мыши
                    break;
                         }
                 }

                 // Состояние каждого подключенного джойстика направляется сюда
                 // при каждом шаге главного цикла движка Irrlicht Engine
                 // сохраняем состояние первого джойстика, игнорируем другие джойстики.
                 // Это на текущий момент поддерживается только в Windows и Linux.
                 if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT
                         && event.JoystickEvent.Joystick == 0)
                 {
                         JoystickState = event.JoystickEvent;
                 }

                 return false;
         }

         const SEvent::SJoystickEvent & GetJoystickState(void) const
         {
                 return JoystickState;
         }

         const SMouseState & GetMouseState(void) const
         {
                 return MouseState;
         }

         MyEventReceiver()
         {
         }

private:
         SEvent::SJoystickEvent JoystickState;
};


Обработчик событий для сохранения нажатых кнопок готов, актуальные ответы получальщика могут быть использованы внутри цикла рендеринга перед отрисовкой сцены. Так что давайте просто создадим irr::IrrlichtDevice и ноды сцены, которые желаем двигать. Мы так же создадим несколько дополнительных объектов, чтобы показать, что есть несколько дополнительных возможностей для перемещения и анимации нод сцены.
Код
int main()
{
         // спросить пользователя про драйвер
         video::E_DRIVER_TYPE driverType=driverChoiceConsole();
         if (driverType==video::EDT_COUNT) return 1;

         // создаем обработчик событий
         MyEventReceiver receiver;

         IrrlichtDevice* device = createDevice(driverType,
                         core::dimension2d< u32 >(640, 480), 16, false, false, false, &receiver);

         if (device == 0)
                 return 1; // не удалось создать выбранный драйвер.

         core::array< SJoystickInfo > joystickInfo;
         // если поддержка джойстика имеется
         if(device->activateJoysticks(joystickInfo))
         {
                 std::cout << "Joystick support is enabled and " << joystickInfo.size()  
                           << " joystick(s) are present." << std::endl;

                 for(u32 joystick = 0; joystick < joystickInfo.size(); ++joystick)
                 {
                         std::cout << "Joystick " << joystick << ":" << std::endl;
                         std::cout << "tName: '" << joystickInfo[joystick].Name.c_str() << "'" << std::endl;
                         std::cout << "tAxes: " << joystickInfo[joystick].Axes << std::endl;
                         std::cout << "tButtons: " << joystickInfo[joystick].Buttons << std::endl;

                         std::cout << "tHat is: ";

                         switch(joystickInfo[joystick].PovHat)
                         {
                         case SJoystickInfo::POV_HAT_PRESENT:
                    std::cout << "present" << std::endl;
                    break;

                         case SJoystickInfo::POV_HAT_ABSENT:
                    std::cout << "absent" << std::endl;
                    break;

                         case SJoystickInfo::POV_HAT_UNKNOWN:
                         default:
                    std::cout << "unknown" << std::endl;
                    break;
                         }
                 }
         }
         else // джойстик не поддерживается
         {
                 std::cout << "Joystick support is not enabled." << std::endl;
         }

         core::stringw tmp = L"Irrlicht Joystick Example (";
         tmp += joystickInfo.size();
         tmp += " joysticks)";
         device->setWindowCaption(tmp.c_str());

         video::IVideoDriver* driver = device->getVideoDriver();
         scene::ISceneManager* smgr = device->getSceneManager();


Мы создадим стрелку(3д модель), ось которой будет представлять импровизированную ручку джойстика и реагировать на отклонения реального джойстика, вдобавок эта "ручка" будет перемещаться вслед за указателем мыши.
Код
scene::ISceneNode * node = smgr->addMeshSceneNode(
                 smgr->addArrowMesh( "Arrow",
                    video::SColor(255, 255, 0, 0),
                    video::SColor(255, 0, 255, 0),
                    16,16,
                    2.f, 1.3f,
                    0.1f, 0.6f
                    )
                 );
         node->setMaterialFlag(video::EMF_LIGHTING, false);

         scene::ICameraSceneNode * camera = smgr->addCameraSceneNode();
         camera->setPosition(core::vector3df(0, 0, -10));

         // Как и в примере 04, мы сделаем движение независимым от частоты кадров.
         u32 then = device->getTimer()->getTime();
         const f32 MOVEMENT_SPEED = 5.f;

         while(device->run())
         {
                 // Рассчитаем временную разницу(DeltaTime).
                 const u32 now = device->getTimer()->getTime();
                 const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // время в секундах
                 then = now;

                 bool movedWithJoystick = false;
                 core::vector3df nodePosition = node->getPosition();

                 if(joystickInfo.size() > 0)
                 {
                         f32 moveHorizontal = 0.f; // Диапазон от -1.f (полное влево) до +1.f (полное вправо)
                         f32 moveVertical = 0.f; // от -1.f (полное вниз) до +1.f (полное вверх).

                         const SEvent::SJoystickEvent & joystickData = receiver.GetJoystickState();

                         // Мы получаем полный аналог диапазона осей(т.е. текущий наклон джойстика), и таким
                         // образом, можем определить мёртвую зону. Это эмпирическое значение, так как  
                         // некоторые джойстики могут дрожать или ползать вокруг центральной точки больше других.
                         // Мы используем диапазон 5% как мёртвую зону, но в целом было бы неплохо, если бы вы
                         // представили пользователю опциональную возможность изменять этот параметр.
                         const f32 DEAD_ZONE = 0.05f;

                         moveHorizontal =
                    (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_X] / 32767.f;
                         if(fabs(moveHorizontal) < DEAD_ZONE)
                    moveHorizontal = 0.f;

                         moveVertical =
                    (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_Y] / -32767.f;
                         if(fabs(moveVertical) < DEAD_ZONE)
                    moveVertical = 0.f;

                         // Информация о POV(Point of View) шляпки(т.е. шляпки-манипулятора дж.)
                         // на данный момент поддерживается только в Windows, но значение  
                         // устанавливается в 65535 если это не поддерживается так что мы можем  
                         // проверить этот диапазон.
                         const u16 povDegrees = joystickData.POV / 100;
                         if(povDegrees < 360)
                         {
                    if(povDegrees > 0 && povDegrees < 180)
                    moveHorizontal = 1.f;
                    else if(povDegrees > 180)
                    moveHorizontal = -1.f;

                    if(povDegrees > 90 && povDegrees < 270)
                    moveVertical = -1.f;
                    else if(povDegrees > 270 || povDegrees < 90)
                    moveVertical = +1.f;
                         }

                         if(!core::equals(moveHorizontal, 0.f) || !core::equals(moveVertical, 0.f))
                         {
                    nodePosition.X += MOVEMENT_SPEED * frameDeltaTime * moveHorizontal;
                    nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime * moveVertical;
                    movedWithJoystick = true;
                         }
                 }

                 // Если нода-стрелка не перемещается джойстиком, она должна следовать за курсором мыши.
                 if(!movedWithJoystick)
                 {
                         // Создать луч на курсор мыши.
                         core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
                    receiver.GetMouseState().Position, camera);

                         // И построим пересечение луча с плоскостью обращённой к камере,
                         // расположенной вокруг ноды(короче нода расположена на этой плоскости
                         // так как плоскость строится в позиции ноды).
                         core::plane3df plane(nodePosition, core::vector3df(0, 0, -1));
                         core::vector3df mousePosition;
                         if(plane.getIntersectionWithLine(ray.start, ray.getVector(), mousePosition))
                         {
                    // Теперь мы имеем позицию мыши в 3d пространстве двигаем ноду к этой позиции.
                    core::vector3df toMousePosition(mousePosition - nodePosition);
                    const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime;

                    if(toMousePosition.getLength() <= availableMovement)
                    nodePosition = mousePosition; // Прыгнуть к финальной позиции
                    else // иначе двигаться к ней
                    nodePosition += toMousePosition.normalize() * availableMovement;
                         }
                 }

                 node->setPosition(nodePosition);

                 // Включает/выключает освещение в зависимости от того нажата ли левая кнопка мыши.
                 node->setMaterialFlag(video::EMF_LIGHTING, receiver.GetMouseState().LeftButtonDown);

                 driver->beginScene(true, true, video::SColor(255,113,113,133));
                 smgr->drawAll(); // отрисовать 3d сцену
                 driver->endScene();
         }


В конце, освободить устройство Иррлихта.
Код
device->drop();

         return 0;
}


Это все.
 
Форум » Игровые движки » IrrLicht Engine » Туториал №19: Джойстик и Мышь
  • Страница 1 из 1
  • 1
Поиск: