Вы уже посмотрели, как программа осуществляет навигацию на карте, но что насчет отображения графики? Программа бесполезна без визуальной обратной связи. Старая добрая функция vInitInterfaceObjects() заботится о загрузке используемых в программе изображений блоков. Вот фрагмент кода, выполняющий этот трюк:
for(int i = 0; i < 3; i++) {
Функция vInitMap() отвечает за создание случайной карты. Взгляните как выглядит код, выполняющий эти действия:
void vInitMap(void)
{
int i;
// Заполнение карты случайными блоками
for(i = 0; i < g_iMapWidth * g_iMapHeight; i++) {
g_iTileMap[i] = rand()%3;
}
}
В заголовочном файле main.h проекта находится несколько исключительно важных типов данных, используемых для просмотра карты. Вот их краткий список:
int g_iTileSize = 32;
int g_iTilesWide = 20;
int g_iTilesHigh = 15;
int g_iMapWidth = 100;
int g_iMapHeight = 100;
int g_iXPos = 0;
int g_iYPos = 0;
int g_iTileMap[10000];
Перед тем как я погружусь в работу функции обновления подразделений, давайте взглянем на следующий код:
// Обновление подразделений
if(timeGetTime() > dwLastUpdateTime) {
vUpdateUnits();
dwLastUpdateTime = timeGetTime() + 33;
}
У вас есть базовые классы для хранения данных подразделения, но как загрузить в них информацию? Один из способов — жестко задать все значения параметров подразделений в коде программы. Подобное сляпанное наспех решение не позволит создать гибкую систему.
Данная функция устанавливает указатели на базовые классы для подразделения. Вы можете сделать это вручную, но наличие одной простой функкции сделает вашу жизнь чуть легче. Вот как выглядит код функции:
void CUnit::vSetBaseValues(CUnitDefense* ptrDef,
CUnitOffense* ptrOff1,
CUnitOffense* ptrOff2,
CUnitOffense* ptrOff3,
Давайте начнем с указателей на базовые типы. В рассматриваемом примере есть тип защиты, три типа атаки, тип перемещения и тип анимации. Я использую три типа атаки потому что на одной боевой единице может быть установлено несколько типов оружия. Например, на танке обычно установлена пушка и пулемет.
Вот мы и рассмотрели все необходимые для подразделения базовые классы. У нас есть готовые к использованию данные защиты, атаки, передвижения и анимации. Отсутствует только клей, который соединит эти разрозненные компоненты вместе. По отдельности эти детали не слишком полезны, но собранные вместе они образуют подразделение.
Функция загрузки пользуется весьма полезной вспомогательной библиотекой DirectX чтобы загрузить графическое изображение из файла в буфер данных текстуры. Вот как выглядит код этой функции:
void CTexture::vLoad(char *szName)
{
// Сохраняем имя файла
strcpy(m_szName, szName);
// загружаем текстуру
D3DXCreateTextureFromFile(m_pd3dDevice, m_szName, &m_pTexture);
}
Здесь начинаются хитрости анимационной графики. Функция загрузки текстур выделяет необходимую для текстур память, а затем в цикле перебирает кадры каждой анимационной последовательности, загружая данные текстур. Но для чего нужна константа UNITMANAGER_MAXOWNERS? Очень хороший вопрос!