Урок Инициализация в Windows я начинаю это пособие непосредственного с кода, разбитого на секции, каждая из которых будет подробно комментироваться. Первое, что вы должны сделать это создать проект в Visual C++



страница27/27
Дата17.11.2018
Размер7.85 Mb.
ТипУрок
1   ...   19   20   21   22   23   24   25   26   27


  {

    keys[wParam] = TRUE;    // Пометить ее как нажатую

    return 0;               // Вернуться

  }


 

  case WM_KEYUP:            // Клавиши была отпущена?

  {

    keys[wParam] = FALSE;   // Отменить пометку



    return 0;               // Вернуться

  }


 

В начале программы необходимо сделать следующие изменения:

 

BYTE  buffer[256];       // Новый буфер вместо Keys[] (Изменено)



bool  active=TRUE;       // Флаг активности окна

bool  fullscreen=TRUE;   // Флаг полноэкранного режима

bool  blend;             // Смешивание ON/OFF

bool  bp;                // Состояние кнопки смешивания

bool  fp;                // Состояние F1 (Изменено)

 

...



 

GLfloat  lookupdown = 0.0f;

GLfloat  z=0.0f;         // Глубина в экран

GLuint  filter;          // Фильтр (Удалено)

 

GLuint texture[5];       // Для текстур (Изменено)



 

В функции WinMain()

 

  // Создание окна OpenGL



  if (!CreateGLWindow("Justin Eslinger's & NeHe's Advanced DirectInput Tutorial",640,480,16,fullscreen))  // (Изменено)

  {


    return 0;            // Выйти, если не удалось создать окно

  }


 

  if (!DI_Init())        // Инициализация DirectInput (Новое)

  {

    return 0;



  }

 

  ...



 

  // Отрисовка сцены, пока окно активно и не была нажата клавиша Esc

  if ((active && !DrawGLScene())) // (Изменено)

 

      ...



  // Обновить состояние клавиатуры (Новое)

  HRESULT hr = g_KDIDev->GetDeviceState(sizeof(buffer), &buffer); 

  if ( buffer[DIK_ESCAPE] & 0x80 )  // Тест клавиши Escape (Изменено)

  {


    done=TRUE;

  }


 

  if ( buffer[DIK_B] & 0x80)    // Нажата клавиша B? (Изменено)

  {

    if (!bp)



    {

      bp = true;                // Нажата клавиша смешения (Новое)

      blend=!blend;

      if (!blend)

      {

        glDisable(GL_BLEND);



        glEnable(GL_DEPTH_TEST);

      }


      else

      {


        glEnable(GL_BLEND);

        glDisable(GL_DEPTH_TEST);

      }

    }


  }

  else


  {

    bp = false;

  }

 

  if ( buffer[DIK_PRIOR] & 0x80 )   // Page Up? (Изменено)



  {

    z-=0.02f;

  }

 

  if ( buffer[DIK_NEXT] & 0x80 )    // Page Down? (Изменено)



  {

    z+=0.02f;

  }

 

  if ( buffer[DIK_UP] & 0x80 )      // Вверх? (Изменено)



  {

    xpos -= (float)sin(heading*piover180) * 0.05f;

    zpos -= (float)cos(heading*piover180) * 0.05f;

    if (walkbiasangle >= 359.0f)

    {

      walkbiasangle = 0.0f;



    }

    else


    {

      walkbiasangle+= 10;

    }

 

    walkbias = (float)sin(walkbiasangle * piover180)/20.0f;



  }

 

  if ( buffer[DIK_DOWN] & 0x80 )    // Вниз? (Изменено)



  {

    xpos += (float)sin(heading*piover180) * 0.05f;

    zpos += (float)cos(heading*piover180) * 0.05f;

    if (walkbiasangle <= 1.0f)

    {

      walkbiasangle = 359.0f;



    }

    else


    {

      walkbiasangle-= 10;

    }

 

    walkbias = (float)sin(walkbiasangle * piover180)/20.0f;



  }

 

  if ( buffer[DIK_LEFT] & 0x80 )    // Влево? (Изменено)



  {

    xpos += (float)sin((heading - 90)*piover180) * 0.05f;  ( Modified )

    zpos += (float)cos((heading - 90)*piover180) * 0.05f;  ( Modified )

    if (walkbiasangle <= 1.0f)

    {

      walkbiasangle = 359.0f;



    }

    else


    {

      walkbiasangle-= 10;

    }

    walkbias = (float)sin(walkbiasangle * piover180)/20.0f;



  }

 

  if ( buffer[DIK_RIGHT] & 0x80 )    // Вправо? (Изменено)



  {

    xpos += (float)sin((heading + 90)*piover180) * 0.05f;  ( Modified )

    zpos += (float)cos((heading + 90)*piover180) * 0.05f;  ( Modified )

    if (walkbiasangle <= 1.0f)

    {

      walkbiasangle = 359.0f;



    }

    else


    {

      walkbiasangle-= 10;

    }

    walkbias = (float)sin(walkbiasangle * piover180)/20.0f;



  }

 

  if ( buffer[DIK_F1] & 0x80)    // F1 нажато? (Изменено)



  {

    if (!fp)                     // Если не была нажата (Новое)

    {

      fp = true;                 // F1 нажата (Новое)



      KillGLWindow();            // Уничтожить текущее окно (Изменено)

      fullscreen=!fullscreen;    // Переключить режим (Изменено)

 

      // Пересоздать окно



      if (!CreateGLWindow("Justin Eslinger's & NeHe's Advanced Direct Input Tutorial",640,480,16,fullscreen))  (Изменено)

      {


         return 0;       // Выйти, если не удалось создать окно (Изменено)

      }


 

      if (!DI_Init())    // Переинициализировать DirectInput (Новое)

      {

        return 0;        // Выйти, если не удалось



      }

    }


  }

  else


  {

    fp = false;          // F1 отпущена

  }

 

  // Shutdown



  // Выход

  DX_End();              // Уничтожить DirectInput (Новое)

  KillGLWindow();        // Уничтожить окно

  return (msg.wParam);   // Выйти из программы

}

 

Функция DrawGLScene() изменилась следующим образом.



 

  glTranslatef(xtrans, ytrans, ztrans);

  numtriangles = sector1.numtriangles;

 

  // Для каждого треугольника



  for (int loop_m = 0; loop_m < numtriangles; loop_m++)

  {


    glBindTexture(GL_TEXTURE_2D, texture[sector1.triangle[loop_m].texture]);  // (Изменено)

 

    glBegin(GL_TRIANGLES);



 

 

Отлично, теперь обсудим все это немного. Мы заменили весь старый код, использующий ввод с клавиатуры средствами Windows на код использующий средства DirectInput. Так же были изменены и сами клавиши управления для удобства использования.



 

Теперь в нашей игре есть поддержка мыши и клавиатуры через DirectInput, что дальше? Нам нужен таймер, для того чтобы регулировать скорость. Без таймера мы обрабатываем клавиатуру каждый кадр, из-за этого скорость перемещения и вращения будет различной на различных компьютерах.

 

Добавим переменную для корректировки и структуру для работы с таймером.



 

POINT  mpos;               

int  adjust = 5;            // Корректировка скорости (Новое)

 

// информация для таймера (Новое)



struct

{

  __int64    frequency;              // Частота



  float    resolution;               // Точность

  unsigned long mm_timer_start;      // Стартовое значение

  unsigned long mm_timer_elapsed;    // Прошедшее время

  bool performance_timer;            // Использовать эффективный таймер

  __int64 performance_timer_start;   // Стартовое значение эффективного таймера

  __int64 performance_timer_elapsed; // Прошедшее время по эффективному таймеру

} timer;

 

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);



 

Этот код обсуждался в уроке 21. Рекомендую просмотреть его.

 

// Инициализация таймера (Новое)



void TimerInit(void)

{

  memset(&timer, 0, sizeof(timer));  // Очистить структуру



  // Проверить есть ли возможность использования эффективного таймера

  if (!QueryPerformanceFrequency((LARGE_INTEGER *) &timer.frequency))

  {

    // нет эффективного таймера



    timer.performance_timer = FALSE;     

    timer.mm_timer_start = timeGetTime(); // Использовать timeGetTime()

    timer.resolution = 1.0f/1000.0f;      // Установить точность .001f

    timer.frequency = 1000;               // Установить частоту 1000

    // Установить прошедшее время равным стартовому

    timer.mm_timer_elapsed = timer.mm_timer_start;

  }

  else


  {

    // доступен эффективный таймер

    QueryPerformanceCounter((LARGE_INTEGER *) &timer.performance_timer_start);

    timer.performance_timer = TRUE;       

 

    // Вычисление точности и частоты



    timer.resolution = (float) (((double)1.0f)/((double)timer.frequency));

    // Установить прошедшее время равным стартовому

    timer.performance_timer_elapsed = timer.performance_timer_start;

  }


}

 

// Получить время в миллисекундах (Новое)



float TimerGetTime()

{

  __int64 time;                // Время храниться в 64-битном целом



  if (timer.performance_timer) // Если используется эффективный таймер

  {


    // Получить текущее время по эффективному таймеру

    QueryPerformanceCounter((LARGE_INTEGER *) &time);

    // вернуть текущее время мину стартовое с данной точностью и в миллисекундах

    return ( (float) ( time - timer.performance_timer_start) * timer.resolution)*1000.0f;

  }

  else


  {

    // вернуть текущее время минус стартовое с данной точностью и в миллисекундах

    return( (float) ( timeGetTime() - timer.mm_timer_start) * timer.resolution)*1000.0f;

  }


}

 

Напомню, что пояснения кода таймера есть в 21-ом уроке. Убедитесь, что к проекту добавлена библиотека winmm.lib.



 

Теперь мы добавим кое-что в функцию WinMain().

 

  if (!DI_Init())           // Инициализация DirectInput  (Новое)



  {

    return 0;

  }

 

  TimerInit();              // Инициализация таймера (Новое)



 

  ...


 

      float start=TimerGetTime();

      // Получить время перед отрисовкой (Новое)

 

      // Отрисовка сцены. Esc – выход.



      // Если окно активно и был выход (Изменено)

      if ((active && !DrawGLScene()))

      {

        done=TRUE;        // ESC DrawGLScene сигнализирует о выходе



      }

      else            // обновить сцену

      {

        // Цикл ожидания для быстрых систем (Новое)



        while(TimerGetTime()

 

Теперь программа должна выполняться с корректной скоростью. Следующая часть кода предназначена для вывода уровня, как в уроке 10.



 

Если вы уже скачали код этого урока, то вы уже заметили, что я добавил несколько текстур для сцены. Новые текстуры находятся в папке Data.

 

Изменения структуры tagTriangle.

 

typedef struct tagTRIANGLE



{

  int  texture; // (Новое)

  VERTEX  vertex[3];

} TRIANGLE;

 

Изменения кода SetupWorld

 

for (int loop = 0; loop < numtriangles; loop++)



{

  readstr(filein,oneline); // (Новое)

  sscanf(oneline, "%i\n", §or1.triangle[loop].texture);  // (Новое)

  for (int vert = 0; vert < 3; vert++)

  {

 

Изменения кода DrawGLScene



 

  // Для каждого треугольника

  for (int loop_m = 0; loop_m < numtriangles; loop_m++)

  {


    // (Модифицировано)

    glBindTexture(GL_TEXTURE_2D, texture[sector1.triangle[loop_m].texture]);

 

    glBegin(GL_TRIANGLES);



 

В функцию LoadGLTextures добавлена загрузка дополнительных текстур

 

int LoadGLTextures()          // Загрузка картинок и конвертирование их в текстуры



{

  int Status=FALSE;           // Статус

  AUX_RGBImageRec *TextureImage[5];         // Массив текстур

  memset(TextureImage,0,sizeof(void *)*2);  // Инициализация указателей NULL

  if( (TextureImage[0]=LoadBMP("Data/floor1.bmp")) &&  // Загрузка текстуры пола

    (TextureImage[1]=LoadBMP("Data/light1.bmp"))&&     // Загрузка текстуры освещения

    (TextureImage[2]=LoadBMP("Data/rustyblue.bmp"))&&  // Стены

    (TextureImage[3]=LoadBMP("Data/crate.bmp")) &&     // решетки

    (TextureImage[4]=LoadBMP("Data/weirdbrick.bmp")))  // потолок

  {


    Status=TRUE;           

    glGenTextures(5, &texture[0]);        // Создание текстур

    for (int loop1=0; loop1<5; loop1++)  

    {


      glBindTexture(GL_TEXTURE_2D, texture[loop1]);

      glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop1]->sizeX,


      TextureImage[loop1]->sizeY, 0,

        GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop1]->data);

      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

    }

    for (loop1=0; loop1<5; loop1++)       



    {

      if (TextureImage[loop1]->data)   

      {

         free(TextureImage[loop1]->data);



      }

      free(TextureImage[loop1]);   

    }

  }


  return Status; // Вернуть статус

}

 



Теперь вы можете использовать возможности DirectInput. Я потратил много времени на написание этого урока и надеюсь, что он вам пригодиться. Спасибо, что потратили свое время на чтение этого урока!
Каталог: forum
forum -> Лечение гепатозов
forum -> Система ведения овцеводства в крестьянско-фермерских и личных хозяйствах населения
forum -> Yaesuft-857 (ft-897) – переходник для подключения cat интерфейса к микрофонному разъему трансивера
forum -> Васильев Владимир Юрьевич
forum -> tl-wr1043ND Беспроводной гигабитный маршрутизатор серии n copyright & trademarks
forum -> Цели и задачи Контакта rtf docx
forum -> Назовите не менее трех результатов революции 1905- 1907гг. Приведите не менее трех положений, отражающих значение революции для отечественной истории начала 20 века


Поделитесь с Вашими друзьями:
1   ...   19   20   21   22   23   24   25   26   27


База данных защищена авторским правом ©vossta.ru 2019
обратиться к администрации

    Главная страница