Данные защиты в электронной таблице Excel
На Рисунок 8.24 показаны уже представленные ранее данные, но в виде гораздо лучше выглядящей электронной таблицы с названиями столбцов. Если у вас есть программа для работы с электронными таблицами или базами данных, экспорт в формат CSV осуществляется очень легко. Загляните в папку проекта D3DFrame_UnitTemplate, находящуюся среди сопроводительных файлов на CD-ROM и вы найдете там папку UnitData, содержащую csv-файлы с информацией о подразделениях, необходимой для данного примера.
Я дал вам краткое изложение, а теперь настало время для кода. В первой части функции я с помощью следующего кода открываю файл с данными типов защиты:
// Открываем файл с данными базового типа fp = fopen(szDefFileName, "r"); if(fp == NULL) { return(-1); } // Читаем строку с заголовками столбцов и игнорируем ее fgets(szTempBuffer, 512, fp); szTempBuffer[strlen(szTempBuffer) - 1] = '\0'; // Устанавливаем общее количество объектов равным 0 m_iTotalDefObjs = 0;После того, как файл открыт, я считываю первую строку текста. Она содержит названия столбцов, так что после чтения эти данные игнорируются. Затем количество объектов защиты устанавливается равным 0. После завершения описанных действий я последовательно считываю каждую строку файла, анализирую ее и инициализирую полученными данными очередной тип защиты. Вот код, выполняющий эти действия:
// Последовательный перебор строк файла while(!feof(fp)) { // Получаем следующую строку fgets(szTempBuffer, 512, fp); if(feof(fp)) { break; } // Добавляем разделитель szTempBuffer[strlen(szTempBuffer)-1] = '\0'; iStart = 0; iEnd = 0; iCurPos = 0; iCurValue = 0; // Извлекаем значение while(szTempBuffer[iCurPos] != '\0' && iCurPos < 512) { // Проверяем достигли ли конца значения if(szTempBuffer[iCurPos] == ',') { iEnd = iCurPos; memset(&szValue[iCurValue][0], 0x00, 32); memcpy(&szValue[iCurValue], &szTempBuffer[iStart], iEnd - iStart); iStart = iEnd + 1; iCurValue++; } iCurPos++; }; // Импорт последнего столбца iEnd = iCurPos; memset(&szValue[iCurValue][0], 0x00, 32); memcpy(&szValue[iCurValue], &szTempBuffer[iStart], iEnd - iStart); iStart = iEnd + 1; iCurValue++; ...Как видите, я извлекаю значения, находящиеся между запятыми и сохраняю их во временном символьном массиве с именем szValue. Как только все значения из строки помещены во временный массив, я копирую их в объект типа защиты. Это происходит в следующем фрагменте кода:
// Идентификатор типа m_DefenseObjs[m_iTotalDefObjs].m_iType = m_iTotalDefObjs; // Название strcpy(m_DefenseObjs[m_iTotalDefObjs].m_szName, &szValue[0][0]); // Коэффициент защиты от пуль m_DefenseObjs[m_iTotalDefObjs].m_iBulletArmorRating = atoi(&szValue[1][0]); // Коэффициент защиты от ракет m_DefenseObjs[m_iTotalDefObjs].m_iMissileArmorRating = atoi(&szValue[2][0]); // Коэффициент защиты от лазера m_DefenseObjs[m_iTotalDefObjs].m_iLaserArmorRating = atoi(&szValue[3][0]); // Коэффициент защиты в рукопашной m_DefenseObjs[m_iTotalDefObjs].m_iMeleeArmorRating = atoi(&szValue[4][0]); // Очки повреждений m_DefenseObjs[m_iTotalDefObjs].m_iMeleeArmorRating = atoi(&szValue[5][0]); // Скорость восстановления m_DefenseObjs[m_iTotalDefObjs].m_iMeleeArmorRating = atoi(&szValue[6][0]); // Увеличиваем количество объектов m_iTotalDefObjs++; } fclose(fp);В приведенном выше коде видно как значения получаются из временного буфера и сохраняются в массиве m_DefenseObj. Как только все значения сохранены, я увеличиваю общее количество объектов типов защиты и вновь повторяю тело цикла. Эти действия повторяются, пока есть информация, которую можно считать из файла; после этого файл закрывается.
Абсолютно так же происходит обработка данных для типов защиты и передвижения. Данные анимации обрабатываются слегка отличным образом. Поскольку данные анимации связханы с графикой, процедура загрузки данных анимации должна загружать не только данные базового типа, но и текстуры. Вот фрагмент кода, который загружает данные для анимации:
// Тип идентификатора m_AnimationObjs[m_iTotalAnimationObjs].m_iType = m_iTotalAnimationObjs; // Имя memset(m_AnimationObjs[m_iTotalAnimationObjs].m_szName, 0x00, 64); strcpy(m_AnimationObjs[m_iTotalAnimationObjs].m_szName, &szValue[0][0]); // Префикс memset(m_AnimationObjs[m_iTotalAnimationObjs].m_szBitmapPrefix, 0x00, 64); strcpy(m_AnimationObjs[m_iTotalAnimationObjs].m_szBitmapPrefix, &szValue[1][0]); // Количество кадров ожидания m_AnimationObjs[m_iTotalAnimationObjs].m_iNumStillFrames = atoi(&szValue[2][0]); // Количество кадров перемещения m_AnimationObjs[m_iTotalAnimationObjs].m_iNumMoveFrames = atoi(&szValue[3][0]); // Количество кадров атаки m_AnimationObjs[m_iTotalAnimationObjs].m_iNumAttackFrames = atoi(&szValue[4][0]); // Количество кадров гибели m_AnimationObjs[m_iTotalAnimationObjs].m_iNumDieFrames = atoi(&szValue[5][0]); // Установка устройства визуализации m_AnimationObjs[m_iTotalAnimationObjs].vSetRenderDevice(m_pd3dDevice); // Загрузка текстур m_AnimationObjs[m_iTotalAnimationObjs].vLoadTextures(); // Увеличение количества объектов m_iTotalAnimationObjs++;Приведенный выше код похож на остальные фрагменты кода за исключением вызовов двух методов объекта анимации. Первый из них, vSetRenderDevice(), устанавливает внутренний указатель объекта анимации на устройство визуализации Direct3D. Это позволяет объекту загружать текстуры. Второй метод, vLoadTextures(), использует информацию, хранящуюся в csv-файле данных анимации для загрузки необходимых для анимации текстур. Он формирует имена файлов, комбинируя заданный в данных анимации префикс растровой графики со значением счетчика кадров. На Рисунок 8.25 показаны данные для типов атаки.