netlib.narod.ru< Назад | Оглавление | Далее >

Использование двухмерных объектов в трехмерном мире

В главе 2, «Рисование с DirectX Graphics», обсуждалось использование щитов (двухмерных объектов, выравниваемых таким образом, что они все время направлены на зрителя), а в этой главе я расскажу об использовании двухмерных объектов, таких как блоки, в трехмерных сценах.

Если хотите увидеть двухмерные объекты в реальной игре, посмотрите на Paper Mario для N64. Марио (и все другие персонажи игры) рисуются как плоские изображения с использованием техники щитов (текстуры, наложенные на плоские полигоны). Весь окружающий Марио мир трехмерен, и при перемещении по нему трехмерная сцена сдвигается, чтобы всегда показывать всех игровых персонажей под правильным углом.

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

Рисование блоков в трехмерном мире

Хотя объединение двухмерных блоков с трехмерными сетками может казаться сложным, ничего нового в нем нет. О том, как загружать и рисовать двухмерные блоки вы узнали в главе 7, «Использование двухмерной графики», а о том, как работать с трехмерными сетками — в главе 2. В этой главе вы узнаете как объединить двухмерные и трехмерные компоненты, чтобы рисовать трехмерную сетку, представляющую уровень игры, и наложить на сетку двухмерные графические блоки, представляющие игровые объекты.

Сейчас вам потребуется трехмерная сетка, представляющая уровень игры. Такая сетка показана на рис. 9.1 и находится на прилагаемом к книге CD-ROM (в папке \BookCode\Chap09\2Din3D). Там же вы найдете растровое изображение, содержащее набор двухмерных блоков, используемых для рисования игрового персонажа.


Рис. 9.1. Большая сетка представляет трехмерный уровень в котором вы будете рисовать двухмерные объекты

Рис. 9.1. Большая сетка представляет трехмерный уровень в котором вы будете рисовать двухмерные объекты


Обычно персонаж перемещается по трехмерному миру (зачастую вдоль единственной оси координат), и при перемещении персонажа передвигается и камера. Камера должна располагаться на небольшом расстоянии от персонажа и чуть выше его, чтобы полностью проявлялся эффект трехмерности уровня. Чтобы увидеть, о чем я говорю, взгляните на рис. 9.2, где показано приложение 2Din3D в действии.


Рис. 9.2. Программа 2Din3D демонстрирует использование двухмерных блоков, в смеси со сложным трехмерным уровнем

Рис. 9.2. Программа 2Din3D демонстрирует использование двухмерных блоков, в смеси со сложным трехмерным уровнем. На рисунке вы видите двухмерный блок (монстра), нарисованный поверх трехмерной сетки, представляющей уровень


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

Загрузка сетки уровня

Графическое ядро является библиотекой полезных функций, и мы воспользуемся им для загрузки X-файла, содержащего сетку уровня. Объект графического ядра, который выполняет загрузку X-файлов, это cMesh. После того, как сетка загружена в объект cMesh, вы создаете объект cObject, используемый для визуализации сетки уровня. В данном примере используется сетка Level.x, которую вы найдете на прилагаемом к книге CD-ROM (в папке \BookCode\Chap09\2Din3D).

// Graphics = ранее инициализированный объект cGraphics
cMesh   LevelMesh; // Сетка уровня
cObject LevelObj;  // Объект, используемый для визуализации

// Загружаем X-файл с именем Level.x
LevelMesh.Load(&Graphics, "Level.x");

// Назначаем сетку объекту
LevelObj.Create(&Graphics, &LevelMesh);

Использовать графическое ядро действительно удобно; показанный выше код — это все, что нам надо. Далее следует загрузка блоков.

Загрузка блоков

Двухмерные блоки в данном примере содержат серию изображений, используемых для рисования анимированного идущего монстра. Эти блоки объединены в одно растровое изображение, загружаемое в объект cTexture. Изображение находится в файле Tiles.bmp на прилагаемом к книге CD-ROM (также в папке \BookCode\Chap09\2Din3D).

// Graphics = Ранее инициализированный объект cGraphics
cTexture Tiles;

// Загружаем текстуру, указав, что цвет 0 - прозрачный 
Tiles.Load(&Graphics, "Tiles.bmp", 0, D3DFMT_A1R5G5B5);

Вы почти готовы начать рисование уровня — сейчас загружены сетка и набор блоков. Однако, перед рисованием сцены, надо выполнить несколько подготовительных действий.

Подготовка к рисованию

Перед визуализацией каждого кадра вы должны выровнять камеру относительно игрока и очистить экранный буфер (и Z-буфер).

// Graphics = ранее инициализированный объект cGraphics
// XPos, YPos, ZPos = координаты персонажа по которому
//                    выравнивается камера
cCamera Camera;

// Очищаем экран и Z-буфер
Graphics.Clear();

// Выравниваем камеру
// (располагая ее перед персонажем и чуть выше)
Camera.Point(XPos, YPos + 50.0f, ZPos - 500.0f,
             XPos, YPos, ZPos);
Graphics.SetCamera(&Camera);

Вы почти закончили; теперь можно рисовать сетку уровня.

Рисование сетки уровня

Вызов cObject::Render позаботится о визуализации сетки уровня. Как и все вызовы визуализации, вы должны поместить его между вызовами cGraphics::BeginScene и cGraphics::EndScene.

if(Graphics::BeginScene()==TRUE) {
    LevelObj.Render();
    Graphics::EndScene();
}

Теперь уровень визуализирован и осталось только нарисовать двухмерные блоки.

Рисование двухмерных объектов

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

ПРИМЕЧАНИЕ
В использовании двухмерных блоков есть один недостаток. Вы не сможете использовать Z-буфер (по крайней мере, если так же как и я используете интерфейс ID3DXSprite), а это значит, что вы не можете просто нарисовать блок и ожидать, что правильное смешивание с трехмерной сценой произойдет автоматически. Нарисованный двухмерный блок будет полностью видим, пока вы не нарисуете поверх него что-нибудь еще (полигон или другой блок).

// Graphics = ранее инициализированный объект cGraphics
// Начинаем сцену
if(Graphics::BeginScene()==TRUE) {

    // Рисуем сетку уровня
    LevelObj.Render();

Теперь уровень визуализирован и можно рисовать двухмерные объекты. Включим альфа-проверку, чтобы прозрачные области блоков отсекались и выключим Z-буферизацию, чтобы ничто не скрывало блоки.

    // Разрешаем прозрачность
    Graphics.EnableAlphaTesting(TRUE);

    // Запрещаем Z-буферизацию
    Graphics.EnableZBuffer(FALSE);

    // Начинаем рисовать спрайты
    Graphics.BeginSprite();

    // Рисуем объект персонажа игрока ( блок размером 64 x 64)
    // основываясь на координатах середины нижней стороны блока.
    // Поскольку камера центрируется по объекту, вам достаточно
    // нарисовать блок в центре экрана (сместив на половину размера
    // блока). Обратите внимание, что 640 и 480 - это размеры экрана
    Tiles.Blit(0, 0, (640-64)/2, 480/2-64, 64, 64);

    // Заканчиваем рисование спрайтов
    Graphics.EndSprite();

    // Отключаем альфа-проверку
    Graphics.EnableAlphaTesting(FALSE);

    // Завершаем рисование сцены
    Graphics::EndScene();
}

Перемещение в трехмерном мире

У неподвижных картинок очень мало применений, так что необходимо добавить к программе немного движения; например, пусть персонаж сможет ходить по уровню. Поскольку персонаж представлен набором трехмерных координат, а уровень является объектом ID3DXMesh, почему бы не воспользоваться функцией ID3DXIntersect для проверки изменения высоты и столкновений персонажа со стенами? Фактически, почему бы не использовать функцию проверки столкновений? Ничто не мешает сделать это, так что двигайтесь вперед и вызывайте функции, разработанные в главе 8, «Создание трехмерного движка».

ПРИМЕЧАНИЕ
Чтобы увидеть, как я добавил проверку пересечений, взгляните на полный исходный код демонстрационной программы 2Din3D, находящейся на прилагаемом к книге CD-ROM (в папке \BookCode\Chap09\2Din3D\). Там вы также найдете некоторые рудиментарные возможности перемещения. В программе вы можете использоватиь клавиши управления курсором для перемещения по уровню. Наслаждайтесь!

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz