Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Создание компьютерных игр


Информационный Канал Subscribe.Ru

Cоздание компьютерных игр.
Выпускается еженедельно по пятницам.
Автор рассылки - Евгений Казеко.

Выпуск 11. (от 8 августа 2003 года)
Программирование Windows. Первые шаги.

--------------------------------------------------------------

После долгого перерыва я вновь приветствую всех читателей рассылки.

Сегодня мы освоим азы, необходимые для создания полноценных игр, работающих под Windows (впрочем как и для любых Windows приложений). Но сперва я хочу сказать несколько слов по поводу самой рассылки, а также сообщить об одном событии.

Столь долгий перерыв был вызван отпуском автора, а также неким творческим кризисом. Мне не хотелось делать неинтересные и бесполезные для читателей выпуски только ради того, чтобы рассылка выходила регулярно, поэтому рассылку пришлось на время прервать. Зато теперь она вновь будет радовать вас выпусками, которые, как я надеюсь, помогут научиться этому увлекательному, но весьма нелегкому делу - созданию компьютерных игр. Теперь рассылка выходит по пятницам, для того чтобы читатели имели возможность изучить выпуски в выходные дни.

В прошлых выпусках мы изучили азы языка программирования С++, столь необходимого для написания игр, а заодно и создали подобие простейшей текстовой ролевой игры. Теперь же мы от программ, запускающихся в консольном окне (сеанс MS DOS) перейдем к написанию полноценных приложений для Windows.

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

Именно по этой причине большинство предыдущих выпусков было посвящено исключительно программированию - ведь графика или музыка без программного кода никогда не станет игрой, как бы хорошо она ни была сделана. Поэтому тем, кого совсем не интересует программирование, придется немного потерпеть. В выпусках мы проходим весь процесс создания игры, от начала и до конца, и говорить о графике, музыке и других аспектах создания игр мы будем именно в тот момент, когда они будут непосредственно использоваться в наших учебных проектах.

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

А тех читателей, которые идут с нами с самого начала, я поздравляю с началом нового раздела нашей рассылки - программирование игр для Windows. Начиная от создания простейшего окна, которое станет "окном, ведущим к работе с графикой" (это мы сделаем сегодня), мы изучим основы создания Windows приложений, и в итоге, через некоторое число выпусков, напишем нашу первую графическую игру - тетрис.

Но прежде чем мы приступим непосредственно к теме выпуска, я хочу сообщить читателям о важном событии, о котором я уже упоминал в начале выпуска. Дело в том, что совсем недавно вышла новая книга "Программирование игр для Windows" Андре Ламота, автора, чье имя хорошо известно большинству создателей игр. Я очень благодарен snowman-у, сообщившему мне об этом событии, так как мне самому была очень нужна подобная книга. Если вы ищете хорошую книгу, которая рассказывает не просто о программировании графики или алгоритмах искуственного интеллекта, а именно о том, как делать игры - это как раз та самая книга, которая вам необходима. В ней вы найдете все, что искали, по крайней мере для меня эта книга стала настольной.

Вот ее краткая аннотация.
В книге рассматриваются основные компоненты DirectX - DirectDraw, DirectSound, DirectInput и DirectMusic, а также вводный курс в программирование с использованием Win32. В книге подробно описаны технологии и алгоритмы двухмерной графики и растеризации. Также в данной книге рассматриваются различные игровые алгоритмы, многопоточное программирование, искусственный интеллект (с использованием нечеткой логики, нейронных сетей и генетических алгоритмов) и стандартные физические модели (гравитация, collision и т.д.).

Книгу вы можете приобрести в книжных магазинах, правда пока далеко не во всех. Вот ссылка на эту книгу в интернет-магазине "Озон": Программирование игр для Windows. Советы профессионала (+ CD-ROM)

А теперь приступим к основной теме. Итак, Windows. Пожалуй, это самая распространенная операционная система для PC. Она обладает собственным графическим интерфейсом и берет на себя большинство задач по обработке графики. Во времена текстовой системы DOS, если вам была нужна программа с графическим интерфейсом, вам приходилось программировать его самостоятельно, так же, как и работать с выводом графики. (Мне вспоминается время, когда программисты напрямую работали с видеопамятью машины, используя низкоуровневый язык Ассемблер). Сейчас же можно сравнительно просто создавать программы со стандартным графическим интерфейсом Windows (кнопочки, меню, полосы прокрутки) - достаточно вызвать соответствующие функции Windows API.

"А что это такое - Windows API?" - спросите вы. API это сокращение от application programming interface, то есть интерфейс программирования приложений. Он представляет собой набор функций, вызывая которые из нашей программы, мы обращаемся к динамически подключаемым библиотекам (.DLL файлы), реализующим те или иные действия.

Сразу хочу отметить, что я не буду глубоко вдаваться в подробности архитектуры Windows, так же как и в подробности программирования Windows приложений. Наша цель - научиться делать игры, и в целях экономии времени мне приходится рассматривать некоторые вопросы достаточно поверхностно, оставляя их углубленное изучение на усмотрение читателей. Поэтому я буду говорить только о самом необходимом, призывая вас как можно больше экспериментировать с примерами программ и изучать различную литературу. Еще раз напомню о сайте Школа создателей компьютерных игр , где можно найти много неплохих материалов.

Структура даже простейшей программы Win32 поначалу вам может показаться очень и очень сложной и совершенно непонятной. Появляется много новых функций, новых типов переменных и других вещей, к которым просто нужно привыкнуть. Они будут повторяться снова и снова, и через некоторое время, работая с исходным ходом программ Win32, вы будете понимать значение каждой строчки. А пока можно просто использовать приведенную ниже программу как "надстройку".

Пока что я приведу текст программы без комментариев, а ниже мы разберем ее. Для запуска программы вам понадобится Microsoft Visual C++, желательно не ниже версии 6. Как работать с этим компилятором, вы сможете узнать из выпуска 4 рассылки. (Запустится ли программа в других компиляторах, я не знаю). Есть еще одна вещь, которую стоит отметить. Если раньше мы при выборе типа проекта выбирали Win32 Console Application (Консольное приложение Windows), то теперь нужно при создании нового проекта выбирать Win32 Application, то есть обычное приложение Windows.

Итак, вот она - программа, которая выведет на текст пустое окно - то самое "окно в мир программирования Windows".


------------------ Начало программы --------------------------------




#include <windows.h>

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style="CS_HREDRAW" | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = "Window Class 1";

     RegisterClass (&wndclass);

     hwnd = CreateWindow ("Window Class 1",           
                          "Window",         
                          WS_OVERLAPPEDWINDOW,         
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,              
                          NULL,                       
                          NULL,                       
                          hInstance,                  
                          NULL) ;                     
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

     
     switch (message)
     {
     case WM_CREATE:
          
          return 0 ;

     case WM_PAINT:

          return 0 ;
          
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}



---------------------------------- Конец программы --------------------------------


Не правда ли, впечатляет? И все это ради какого-то пустого окна. Вам вероятно кажется, что для такой простой задачи программа слишком большая. Поверьте мне, это не так. Наше окно можно переместить, изменить его размер, закрыть, свернуть... Если бы вы захотели написать нечто подобное в DOS, ваша программа была бы гораздо больше. А здесь мы вызвали несколько стандартных функций Windows и все.

Начнем детальный разбор программы.


------------------ Начало программы --------------------------------



/* Этот заголовочный файл как раз и описывает вызовы стандартных функций */
#include <windows.h>



/* Что это такое? Это объявление так называемой оконной процедуры WndProc, нужной
   для обработки сообщений Windows. О сообщениях Windows мы поговорим позже, а
   что касается новых типов данных (большими буквами), то нам пока будет интересен
   только тип HWND, который создан специально для ссылок на окно (описателей окна).
*/

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



/* А это функция WinMain, которая заменяет столь привычную в консольных
   приложения функцию main. Именно с нее начинается выполнение программы.
*/



int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{

/* Объявляем несколько переменных, используя новые типы. Эти типы данных
   являются структурами. Мы говорили о том, что такое структуры, не так ли?
*/    

// Это структура ссылки на окно
     HWND         hwnd ;

// Это структура, в которой будет хранится информация о сообщениях
     MSG          msg ;

/* А это структура класса окна, которая нам сразу же и понадобится.
   В ней мы будем описывать свойства окна, которые нам необходимы.
   Наибольший интерес представляют собой переменные hIcon (указывает
   на пиктограмму окна), hCursor (указывает на курсор), hbrBackground
   (задает цвет фона).
*/
     WNDCLASS     wndclass ;

     wndclass.style="CS_HREDRAW" | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = "Window Class 1";

// Регистрируем класс окна

     RegisterClass (&wndclass);

// Создаем окно
// Для получения доступа и работы с окном используем переменную hwnd

     hwnd = CreateWindow ("Window Class 1",           
                          "Window",   // заголовок окна      
                          WS_OVERLAPPEDWINDOW,         
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,              
                          CW_USEDEFAULT,              
                          NULL,                       
                          NULL,                       
                          hInstance,                  
                          NULL) ;                     

// Отображаем окно. В этот момент оконной процедуре посылается сообщение WM_CREATE
    
     ShowWindow (hwnd, iCmdShow) ;

// Обновляем окно. Посылается сообщение WM_PAINT
     UpdateWindow (hwnd) ;

// Обрабатываем сообщения     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }

     return msg.wParam ;

// Окно закрыто. Программа завершена
}




/* Это оконная процедура, которая обрабатывает системные сообщения. 
   В случае, если мы не опишем, как обрабатывать сообщение, оно
   будет обработано процедурой по умолчанию.
*/

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

     
     switch (message)
     {
     case WM_CREATE:  // сообщение создания окна
          
          return 0 ;

     case WM_PAINT:   // сообщение обновления окна

          return 0 ;
          
     case WM_DESTROY: // сообщение закрытия окна

   // Эта функция посылает сообщение выхода, после чего программа завершается
          PostQuitMessage (0) ;
          return 0 ;
     }

     // Процерура обработки сообщений по умолчанию
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}



---------------------------------- Конец программы --------------------------------


А теперь поговорим о том, как это все работает. В нашей программе две функции - WinMain и оконная процедура. Начнем с WinMain.

1) Сперва нам нужно создать оконный класс, на основе которого мы будем создавать окна, в нашем случае это единственное окно. Именно здесь мы задаем вид курсора, цвет фона, а также ссылаемся на оконную процедуру.

2) Теперь нужно зарегистрировать созданный класс в системе, давая программе знать, на основе какого класса будут строиться новые окна программы.

3) Затем мы создаем окно на основе нашего класса, используя hwnd в качестве ссылки на наше окно.

4) Теперь мы выводим окно на экран и начинаем принимать сообщения. И тут в ход вступает оконная процедура.

Зачем она нужна? Дело в том, что программа постоянно принимает от системы различные сообщения. Когда мы двигаем мышь, когда мы перемещаем окно, сворачиваем его или закрываем, когда мы нажимаем клавишу - программа получает от Windows соответствующее сообщение. Эти сообщения программа сохраняет в структуре msg и обрабатывает их оконной процедурой. Мы можем не обрабатывать все сообщения (их очень и очень много), тогда они будут обработаны процедурой по умолчанию.

При закрытии окна программа завершается. Вот собственно и все, в этом нет ничего сложного, но к этому нужно привыкнуть, если видишь это впервые. С создания окна все и начинается. В следующих выпусках мы посмотрим, что можно вывести в нашем пустом окне. А пока что я желаю вам удачного разбора программы.

До следующего выпуска!

--------------------------------------------------------------

Архив рассылки вы найдете по адресам http://subscribe.ru/catalog/comp.games.gamecoder и http://www.gamecoder.nm.ru/subscribe.htm.

Евгений Казеко.
kazeko@list.ru
www.gamecoder.nm.ru
-----------------------------
Рассылка "Создание компьютерных игр", выпуск 11.
Выпускается еженедельно по средам.



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное