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

Глава 7. Использование двухмерной графики

Рис. 7.1. В рисовании больших двухмерных сцен блоки и карты идут рука об руку. Вы используете изображенные слева блоки для визуализации карты справа

Польза от использования блоков и карт ясна — они требуют очень мало памяти для хранения. Используя для карты формат «раскрась по номерам» вы сможете конструировать огромные (именно огромные) сцены, тратя на них очень мало памяти.

Предположим, к примеру, что используются блоки размером 16 × 16 пикселов. Предположим, что вы используете 8-разрядный цвет, тогда для набора из 256 блоков потребуется 65 536 байт памяти. Кроме того, у вас есть карта, представляющая собой массив байтов (каждый байт представляет номер рисуемого блока) размером 1024 × 1024 (1 048 576 байт). Итак, всего для хранения карты и блоков вам требуется 1 114 112 байт.

Поскольку размер каждого блока равен 16 пикселям, а размер карты — 1024 блока, в результате визуализации получается изображение размером 16 384 × 16 384 пиксела, для хранения которого требуется 268 435 456 байт. Вы видите как экономится память вместо почти 300 Мбайт чуть больше 1 Мбайт.

ПРИМЕЧАНИЕ

Здесь мы сделали краткий обзор основ использования

 

блоков и карт. Вы могли не понять насколько далеко

 

простирается концепция использования блоков. Несмотря

 

на то, что вы рисуете прямоугольные блоки, сама графика

 

не должна быть прямоугольной, и даже не должна

 

рисоваться на экране в виде прямоугольной решетки.

 

 

Использование блоков с DirectX

Как вы уже видели в предыдущей главе, нарисовать небольшой прямоугольный текстурированный полигон, который замечательно подойдет

для представления ваших блоков, совсем не сложно. Вы можете выполнить это с помощью специального объекта D3DX с именем ID3DXSprite. В главе 6, «Создаем ядро игры», я упоминал интерфейс ID3DXSprite, когда

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

352

netlib.narod.ru

Джим Адамс

У объекта ID3DXSprite одна задача — рисовать на экране

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

Чтобы начать использовать блоки в Direct3D, объявите экземпляр объекта ID3DXSprite и используйте для его инициализации функцию

D3DXCreateSprite:

// g_pD3DDevice = ранее инициализированный объект устройства

ID3DXSprite *pSprite = NULL;

if(FAILED(D3DXCreateSprite(g_pD3DDevice, &pSprite))) {

// Произошла ошибка

}

Как видите, функция D3DXCreateSprite получает два параметра —

указатель на ранее инициализированный объект трехмерного устройства и указатель на создаваемый объект ID3DXSprite. После этого вызова

функции все готово к работе. Вам необходимо только загрузить текстуру,

представляющую блок (или блоки), который вы собираетесь рисовать и воспользоваться функцией ID3DXSprite::Draw для рисования блока:

HRESULT ID3DXSprite::Draw(

//

Используемая текстура

IDirect3DTexture9 *pSrcTexture,

CONST RECT

*pSrcRect,

//

Прямоугольник источника

CONST D3DXVECTOR2

*pScaling,

//

Вектор масштабирования

CONST D3DXVECTOR2

*pRotationCenter, //

Центр вращения

FLOAT

Rotation,

//

Угол поворота

CONST D3DVECTOR2

*pTranslation,

//

Вектор перемещения

D3DCOLOR

Color);

//

Модуляция цвета

Трюк в использовании функции Draw заключается в конструировании структуры RECT для прямоугольника источника, содержащей координаты

фрагмента внутри текстуры, который вы хотите использовать как блок. Например, у вас есть текстура, размером 256 × 256 пикселей, содержащая 64 блока (каждый размером 32 × 32 пикселя), упакованных в 8 строк и 8 столбцов (как показано на рис. 7.2).

Рис. 7.2. 64 блока, упорядоченные в таблицу 8 × 8

netlib.narod.ru

353

Глава 7. Использование двухмерной графики

СОВЕТ Чтобы повысить эффективность, упаковывайте в используемую для блоков текстуру столько блоков, сколько можете поместить и располагайте их в виде строк и столбцов. Например, если у вас 64 блока размером 32 × 32 пиксела, создайте растровое изображение для хранения 8 строк и 8 столбцов блоков, что дает вам текстуру размером 256 × 256 пикселей. Такое упорядочивание блоков показано на рис. 7.2. Блоки последовательно нумеруются, начиная с верхнего левого угла. Блок, находящийся в левом верхнем углу — это блок 0. Справа от него находится блок 1 и так далее, по всем строкам, пока не доберемся до блока 63 (нижнего правого блока). В этом случае вы ссылаетесь на блок по его номеру и позволяете процедуре рисования блока самой вычислять его координаты в текстуре.

Если вы рисуете второй слева и третий сверху блок, прямоугольник источника будет занимать координаты от 64, 96 до 96, 128. Поскольку размер всех блоков 32 × 32, необходимо знать только координаты верхнего левого угла блока в текстуре; для вычисления нижней и правой координат блока достаточно просто прибавить 32. Вот как инициализируется структура RECT

с использованием этих значений:

RECT SrcRect;

= 64;

// Левая координата блока

SrcRect.left

SrcRect.top

= 96;

// Верхняя координата блока

SrcRect.right

=

SrcRect.left

+ 32; // Добавляем ширину блока

SrcRect.bottom

=

SrcRect.top

+ 32; // Добавляем высоту блока

Обратите внимание, что если pSrcRect присвоить значение NULL, то

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

масштабировать размеры блока. Если вы не будете использовать масштабирование, укажите NULL; в ином случае сконструируйте вектор,

содержащий коэффициенты масштабирования.

СОВЕТ

Возможность масштабировать блоки в Direct3D открывает

 

некоторые удивительные возможности. Вы можете

 

использовать небольшие изображения, скажем

16 × 16

 

пикселей, и рисовать их в большем размере, например,

 

64 × 64 пикселя. При рисовании блока

текстура

растягивается, чтобы соответствовать масштабированному блоку. Применяя для карт такие масштабируемые блоки вы можете значительно увеличить размеры карт и в то же время сэкономить память, используемую для текстур блоков. Я подробнее расскажу об этой техинке в разделе «Работа с большими растрами» этой главы.

354

netlib.narod.ru

Джим Адамс

Масштабирование — это единственная из специальных возможностей

работы с блоками, которую я собираюсь использовать. Так что вы можете присвоить pRotationCenter значение NULL, а Rotation — 0,0.

Заслуживает внимания параметр pTransform, представляющий собой

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

Последний аргумент функции Draw — это Color, являющийся значением типа D3DCOLOR, используемым для корректировки выходной

текстуры. Обычно вы здесь задаете значение 0xFFFFFFFF, чтобы блоки

рисовались точно так же, как они выглядят в текстуре, но, используя макрос D3DCOLOR_RGBA вы можете при рисовании изменять цвета или альфа-

значения блоков.

Например, чтобы нарисовать блок с половинным альфа-значением, используйте:

D3DCOLOR_RGBA(255,255,255,127); // 127 = половина

Как видите, значения берутся из диапазона от 0 (цвет или альфазначение удаляется) до 255 (цвет или альфа-значение остается неизменным). Точно так же, как мы меняли альфа-значение, можно полностью вырезать красную составляющую, используя следующий код:

D3DCLOR_RGBA(0,255,255,255); // 0 = нет цвета

Это открывает ряд роскошных возможностей, таких как создание дневных и ночных сцен или блоки, через которые видна расположенная за ними графика (например, окна).

Вернемся к основной теме и посмотрим, как можно использовать функцию Draw для рисования блоков. Ниже приведен пример функции, которая получает текстуру, координаты источника и координаты места назначения для рисования блока (обратите внимание, что у координат тип float, хотя они определены в экранном пространстве, то есть в размерах области отображения).

//Убедитесь, что перед вызовом этой функции вы вызвали

//IDirect3DDevice::BeginScene и загрузили текстуру,

//используемую для хранения блоков

//pSprite = ранее инициализированный объект ID3DXSprite void DrawTile(float SrcX, float SrcY,

float DestX, float DestY,

float TileWidth, float TileHeight float ScaleX, float ScaleY, IDirect3DTexture9 *pTileTexture, D3DCOLOR Color)

{

RECT SrcRect; // Прямоугольник источника

netlib.narod.ru

355

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