Теперь, после того как базовая информация о подразделених загружена, вы можете создавать подразделения, которые будут использоваться в игре. Вы не можете модифицировать базовые типы, так что следует создавать новые объекты подразделений. Здесь в игру вступает член данных диспетчера подразделений с именем m_UnitObjs. Данный массив хранит модифицируемые объекты подразделений, использующиеся в игре. Для управления этими объектами применяются две функции: iAddUnit() и vRemoveUnit().
Функция CUnitManager::iAddUnit()
Когда вы хотите ввести в игру новое подразделение, следует вызвать функцию добавления подразделения. Она находит неактивное подразделение и инициализирует его данные для использования в игре. Вот как выглядит код этой функции:
int CUnitManager::iAddUnit(char *szName, int iOwner)
{
int i;
int iFoundID = -1;
// Ищем соответствующий тип
for(i = 0; i < m_iTotalUnitBaseObjs; i++) {
if(!stricmp(szName, m_UnitBaseObjs[i].m_szName)) {
iFoundID = i;
break;
}
}
// Возвращаемся, если базовый тип не найден
if(iFoundID == -1) {
return(-1);
}
// Ищем свободный блок данных подразделения
for(i = 0; i < m_iTotalUnitObjs; i++) {
// Проверяем, является ли блок неактивным
if(!m_UnitObjs[i].m_bActive) {
// Активируем подразделение
m_UnitObjs[i].m_bActive= 1;
// Устанавливаем его внутренние типы
m_UnitObjs[i].vSetBaseValues(
m_UnitBaseObjs[iFoundID].m_Defense,
m_UnitBaseObjs[iFoundID].m_Offense1,
m_UnitBaseObjs[iFoundID].m_Offense2,
m_UnitBaseObjs[iFoundID].m_Offense3,
m_UnitBaseObjs[iFoundID].m_Movement,
m_UnitBaseObjs[iFoundID].m_Animation);
// Устанавливаем тип подразделения
m_UnitObjs[i].m_iType = iFoundID;
// Устанавливаем владельца подразделения
m_UnitObjs[i].m_iOwner = iOwner;
// Увеличиваем количество подразделений у владельца
m_iOwnerTotal[iOwner]++;
return(i);
}
}
return(-1);
}
Первая часть кода функции в цикле перебирает все базовые типы подразделений и пытается найти тот из них, название которого совпадает со строкой, переданной в параметре функции. Если совпадение найдено, сохраняется идентификатор подразделения и выполнение функции продолжается.
Следующая часть кода в цикле перебирает список всех подразделений игрока, ища неактивную запись. Данный этап необходим потому что активные подразделения уже присутствуют в игре и мы не можем использовать здесь относящиеся к ним записи. После обнаружения неактивного подразделения, оно делается активным и выполняется установка его базовых типов. В конце задается тип подразделения и его владелец. Я также отслеживаю сколько подразделений находится у каждого владельца, чтобы не превысить установленный лимит, если он существует.
Еще раз проясню ситуацию: массив m_UnitObjs хранит данные подразделений, которые изменяются во время игры, а массив m_UnitBaseObjs хранит шаблоны подразделений, которые никогда не меняются. Объекты m_UnitObjs меняют свои данные состояния, а объекты m_UnitBaseObjs — нет.
Управление текстурами
Я уже показывал вам управление текстурами ранее, в разделе посвященном импорту данных подразделений. Поскольку функция iLoadBaseTypes() загружает все тербуемые текстуры, можно считать, что управление текстурами уже реализовано. Тем не менее, я добавил еще одну функцию управления, которая подсчитывает количество загруженных текстур и возвращает полученное значение. Она полезна при вычислении объема используемой для хранения текстур памяти. Функция называется iCountTotalTextures(), и вот как выглядит ее код:
int CUnitManager::iCountTotalTextures(void)
{
int iCount = 0;
// Цикл перебора объектов анимации и подсчета текстур
for(int i = 0; i < m_iTotalAnimationObjs; i++) {
iCount += m_AnimationObjs[i].m_iTotalTextures;
}
return(iCount);
}
В функции я перебираю все загруженные базовые типы анимации и суммирую количество текстур, содержащееся в каждом из них. После того, как цикл завершен я возвращаю итоговое значение вызывающей программе. Поскольку каждая текстура в данной игре имеет размер 128x128 точек и глубину цвета 32 бит, для вычисления объема занимаемой текстурами памяти вам достаточно умножить возвращаемое функцией общее количество текстур на 65536 (128 x 128 x 4).