Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming / GameProg / RPG_Programming_2ed.pdf
Скачиваний:
240
Добавлен:
12.02.2016
Размер:
12.06 Mб
Скачать

Глава 8 Создание трехмерного

графического движка

В главе 2, «Рисование с DirectX Graphics» вы узнали, как визуализировать трехмерную графику, но работали только с небольшими сетками. Теперь вам нужна возможность визуализировать большие карты и уровни, по которым будут бродить игроки. Вы уже видели, как работать с двухмерными мирами — теперь пришло время перейти к трехмерному миру!

В этой главе вы узнаете следующее:

Использование сеток в качестве уровней.

Использование пирамиды видимого пространства.

Визуализация уровней с использованием узлов и деревьев.

Добавление в мир трехмерных объектов.

Обнаружение столкновений.

Небесный куб.

Сетки в качестве уровней

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

Это не должно обескураживать вас, поскольку есть несколько замечательных способов использования одной сетки для визуализации уровня. Предположим, мир вашей игры состоит исключительно из подземелий. Каждое подземелье состоит из различных комнат, соединенных коридорами. Видите, что получается? Каждая комната и коридор — это отдельная сетка; вам надо только загружать и освобождать представляющие комнаты подземелья сетки по ходу игрового процесса.

netlib.narod.ru

379

Глава 8. Создание трехмерного графического движка

Чтобы увидеть, о чем я говорю, загрузите демонстрационную программу MeshLvl, находящуюся на прилагаемом к книге CD-ROM (посмотрите в папке BookCode\Chap08\MeshLvl\). Программа показывает загрузку нескольких сеток и их совместное рисование в виде большого уровня. На рис. 8.1 показано окно программы MeshLvl.

Рис. 8.1. Программа MeshLvl в действии. Обратите внимание, что для рисования различных комнат используются только две сетки

Вот как работает программа MeshLvl: главная функция (которую мы разберем здесь) загружает две сетки — коридор и комнату. Каждый коридор и комната в игре представлены объектом cObject из графического ядра, с

которым в свою очередь связана соответствующая сетка. Для визуализации сцены вам необходимо ориентировать коридоры и комнаты относительно

местоположения зрителя и нарисовать их, используя функции визуализации сеток, такие как cObject::Render. В демонстрационной программе вы

можете использовать клавиши управления курсором для перемещения по коридорам и комнатам и мышь для вращения камеры.

Загрузка уровней

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

экземпляры класса трехмерных объектов (cObject). Для загрузки

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

380

netlib.narod.ru

Джим Адамс

//Объявления в классе cMesh m_LevelMeshes[2]; cObject m_LevelObjects[8];

//... далее в коде инициализации

//Загрузка сеток комнат

m_RoomMeshes[0].Load(&m_Graphics, "..\\LevelData\\Corridor.x", "..\\LevelData\\");

m_RoomMeshes[1].Load(&m_Graphics, "..\\LevelData\\Room.x", "..\\LevelData\\");

// Установка объектов комнат m_RoomObjects[0].Create(&m_Graphics, &m_RoomMeshes[1]); m_RoomObjects[1].Create(&m_Graphics, &m_RoomMeshes[0]); m_RoomObjects[2].Create(&m_Graphics, &m_RoomMeshes[1]); m_RoomObjects[3].Create(&m_Graphics, &m_RoomMeshes[0]); m_RoomObjects[4].Create(&m_Graphics, &m_RoomMeshes[0]); m_RoomObjects[5].Create(&m_Graphics, &m_RoomMeshes[1]); m_RoomObjects[6].Create(&m_Graphics, &m_RoomMeshes[0]); m_RoomObjects[7].Create(&m_Graphics, &m_RoomMeshes[1]);

В предшествующем коде показана загрузка двух сеток: Corridor.x и Room.x. Для хранения сеток используется пара объектов cMesh. Затем создается восемь объектов (каждый из которых является экземпляром cObject), представляющих комнаты (или соединяющие их коридоры). Теперь комнаты и коридоры необходимо ориентировать:

//m_RoomMeshes[0], [2], [5], [7] используют сетку комнаты (room.x)

//m_RoomMeshes[1], [3], [4], [6] используют сетку коридора (corridor.x) m_RoomObjects[0].Move(-2000.0f, 0.0f, 2000.0f);

m_RoomObjects[1].Move(

0.0f,

0.0f,

2000.0f);

m_RoomObjects[2].Move( 2000.0f,

0.0f,

2000.0f);

m_RoomObjects[3].Move(-2000.0f,

0.0f,

0.0f);

m_RoomObjects[4].Move( 2000.0f,

0.0f,

0.0f);

m_RoomObjects[5].Move(-2000.0f,

0.0f, -2000.0f);

m_RoomObjects[6].Move(

0.0f,

0.0f, -2000.0f);

m_RoomObjects[7].Move( 2000.0f,

0.0f, -2000.0f);

m_RoomObjects[0].Rotate(0.0f, 0.00f, 0.0f); m_RoomObjects[1].Rotate(0.0f, 1.57f, 0.0f); m_RoomObjects[2].Rotate(0.0f, 1.57f, 0.0f); m_RoomObjects[5].Rotate(0.0f, -1.57f, 0.0f); m_RoomObjects[6].Rotate(0.0f, -1.57f, 0.0f); m_RoomObjects[7].Rotate(0.0f, 3.14f, 0.0f);

Ну вот! Все готово к рисованию комнат.

Рисование комнат

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

netlib.narod.ru

381

Глава 8. Создание трехмерного графического движка

По указанной причине код, визуализирующий представление, получается очень простым. Перебирая в цикле элементы массива, хранящие ориентацию каждой из комнат, программа визуализирует каждую сетку, используя короткую последовательность команд. В приведенном ниже коде вы увидите короткий цикл, занимающийся ориентированием и рисованием комнат. Также обратите внимание, что я добавил код для чтения пользовательского ввода и соответствующего перемещения точки просмотра (с использованием объекта cCamera).

Клавиши управления курсором перемещают точку просмотра, а перемещение мыши изменяет направление взгляда. В каждом кадре экранные координаты мыши (по оси X) преобразуются в значение поворота относительно оси Y. При перемещении мыши влево или вправо соответственно влево иди вправо поворачивается направление взгляда. Поворот относительно оси Y сохраняется в объекте cCamera, представляющем местоположение зрителя в трехмерном мире.

Когда пользователь нажимает клавишу управления курсором, вращение по оси Y используется для перемещения зрителя. Зритель перемещается вперед, назад, влево или вправо на расстояние, определяемое по времени, прошедшему с предыдущего вызова Frame до текущего вызова Frame (оно

хранится в переменной Elapsed). Направление перемещения определяется

по повороту относительно оси Y, вычисляемому на основе координаты X мыши.

Взгляните на функцию, которая обрабатывает визуализацию и ввод:

BOOL cApp::Frame()

{

static DWORD Timer = timeGetTime(); unsigned long Elapsed;

float XMove, ZMove; short i;

//Вычисляем прошедшее время

//(плюс повышение скорости)

Elapsed = (timeGetTime() - Timer) * 2; Timer = timeGetTime();

// Получаем ввод m_Keyboard.Read(); m_Mouse.Read();

//Обрабатываем ввод и обновляем все.

//ESC завершает программу

if(m_Keyboard.GetKeyState(KEY_ESC) == TRUE) return FALSE;

 

// Обработка перемещения

 

XMove = ZMove = 0.0f;

 

// Обработка ввода с клавиатуры для

 

// перемещения зрителя

 

if(m_Keyboard.GetKeyState(KEY_UP) == TRUE) {

 

XMove = (float)sin(m_Camera.GetYRotation()) * Elapsed;

 

ZMove = (float)cos(m_Camera.GetYRotation()) * Elapsed;

 

}

382

netlib.narod.ru

Соседние файлы в папке GameProg