Цвета владельца
Здесь начинаются хитрости анимационной графики. Функция загрузки текстур выделяет необходимую для текстур память, а затем в цикле перебирает кадры каждой анимационной последовательности, загружая данные текстур. Но для чего нужна константа UNITMANAGER_MAXOWNERS? Очень хороший вопрос!
Давайте еще раз взглянем на код, вычисляющий общее количество кадров:
m_Textures = new CTexture[ (m_iNumStillFrames * (UNITMANAGER_MAXOWNERS + 1)) + (m_iNumMoveFrames * (UNITMANAGER_MAXOWNERS + 1)) + (m_iNumAttackFrames * (UNITMANAGER_MAXOWNERS + 1)) + (m_iNumDieFrames * (UNITMANAGER_MAXOWNERS + 1))];
Все выглядит нормально, за исключением операций умножения. Константа UNITMANAGER_MAXOWNERS содержит общее количество доступных в игре цветов игроков. Я использую это значение, чтобы узнать, сколько различных цветов для игроков поддерживает игра. Если вы раньше уже играли в стратегические игры, то знаете, что подразделения разных игроков отмечаются разными цветами. У одного игрока на боевых единицах могут быть красные полоски, в то время как у другого игрока эти же полоски будут пурпурными. Для этого необходимы дополнительные кадры анимации: для каждого кадра анимации столько, сколько доступно цветов.
Например, если в анимационной последовательности ожидания один кадр, вам необходим этот кадр плюс по одному кадру для каждого доступного цвета владельца. Общее количество кадров вычисляется по формуле:
Количество_кадров_анимации * (Количество_цветов + 1)
Я прибавляю к количеству цветов 1, чтобы учесть исходный кадр. Кадры с цветами содержат только информацию о раскраске боевой единицы, в то время как исходный кадр содержит изображение самого подразделения. Если вам трудно это понять, взгляните на рис.8.18.
Рис. 8.18. Кадры с цветами владельца для вертолета Apache
На рис. 8.18 показаны кадры состояния ожидания для вертолета Apache. Первый кадр содержит изображение самой боевой единицы. На нем вы видите корпус вертолета, оружие, механизмы и лопасти пропеллера. На следующих кадрах изображена только накладываемая на исходное изображение раскраска. В примере поддерживается только четыре варианта раскраски, так что вы видите четыре кадра, каждый со своим цветом. Черно-белые изображения вам не слишком помогут, так что лучше загрузить графику из сопроводительных файлов. Она находится в каталоге D3DFrame_UnitTemplate\UnitData. Загрузите файлы apache0_0.tga, apache0_1.tga, apache0_2.tga, apache0_3.tga и apache0_4.tga. Файл apache0_0.tga содержит базовое изображение, а остальные файлы содержат только данные о цветах владельца.
Спрашивается, как это влияет на анимационную последовательность? Весьма сильно! И снова одна картинка гораздо лучше тысячи слов, так что смотрите на рис. 8.19.
Рис. 8.19. Анимационная последовательность для танка с учетом цветов владельца
На рис. 8.19 показаны анимационная последовательность ожидания и анимационная последовательность передвижения для танка, которые я уже демонстрировал ранее. Однако здесь в них внесено несколько изменений. Во-первых увеличилось количество кадров анимации. Это вызвано тем, что помимо основного кадра теперь в последовательности присутствуют и кадры с цветами владельца. Результат ясно виден на кадре анимации ожидания. Анимация ожидания состоит из одного кадра, но вместе с ним хранятся данные кадров с четырьмя цветами владельцев. Теперь только для анимации ожидания требуется целых пять кадров.
Взгляните таже на приведенную на рис. 8.19 анимационную последовательность передвижения. В предыдущем примере я показал вам, что кадры анимации передвижения размещаются один за другим. На самом деле между ними располагаются кадры с цветами владельца. Первый кадр анимации передвижения находится в кадре с номером 5, и за ним следуют четыре кадра с цветами владельца. Следующий кадр анимационной последовательности передвижения расположен в десятом кадре, и за ним так же следуют четыре кадра с цветами. Последний кадр анимации передвижения находится в кадре с номером 15 и за ним следуют последние четыре кадра с цветами владельца, необходимые для анимации.
Давайте еще раз взглянем на цикл, загружающий кадры анимации ожидания:
m_iStartStillFrames = 0; for(i = 0; i < m_iNumStillFrames; i++) { for(j = 0; j < UNITMANAGER_MAXOWNERS+1; j++) { sprintf(szBitmapFileName, "UnitData\\%s%d_%d.tga", m_szBitmapPrefix, iLocalCount, j);
// Задаем устройство визуализации m_Textures[m_iTotalTextures].vSetRenderDevice(m_pd3dDevice); // Загружаем текстуру m_Textures[m_iTotalTextures].vLoad(szBitmapFileName); // Увеличиваем общее количество текстур m_iTotalTextures++; } iLocalCount++; }
Сначала я указываю, что анимация ожидания начинается с кадра с номером 0. Поскольку анимационная последовательность ожидания является самой первой в массиве, она начинается с кадра с индексом 0.
Затем следует внешний цикл. Он перебирает все кадры, входящие в заданную анимационную последовательность. В примере с танком для анимации ожидания требуется только один кадр, поэтому тело цикла выполнится только один раз.
Теперь начинается внутрений цикл. Количество его выполнений равно количеству цветов владельца плюс один. Благодаря этому он загружает базовый кадр анимации и все кадры с цветами владельца для каждого кадра анимационной последовательности. Внутири цикла на лету создаются имена загружаемых файлов по следующему шаблону:
UnitData\\ПрефиксТекстуры_НомерКадра_НомерЦвета.tga
Вместо поля ПрефиксТекстуры подставляется префикс имени файла с текстурой. Для танка вы можете выбрать префикс «TankGraphic». Для вертолета Apache я использую префикс «Apache».
Поле НомерКадра заменяется на номер кадра в анимационной последовательности. Поскольку анимационная последовательность для ожидания состоит из одного кадра, в это поле помещается 0.
Поле НомерЦвета содержит номер загружаемого кадра с цветами владельца. Базовому кадру с изображением боевой единицы соответствует номер 0.
После того, как название файла создано, я задаю устройство визуализации для объекта текстуры, после чего вызываю функцию загрузки объекта текстуры. Завершив эти действия я увеличиваю счетчик общего количества загруженных текстур и заканчиваю цикл.