Структура этой программы редактирования карт практически полностью повторяет структуру предыдущего примера. Главные отличия сконцентрированы в функции генерации карты. Ее цель — генерировать случайно расположенные участки суши, базируясь на передаваемом в качестве параметра номере используемого алгоритма. В рассматриваемом примере я реализовал только один тип алгоритма генерации карты, но ничто не мешает вам добавить и другие! Вот как выглядит код функции:
void vGenerateMap(int iType)
{
int iRandDirection;
int iSeedPos[32];
int i, j;
int iNumSeeds = 32;
int iNumUpdates = 800;
// -- ТИП 0 -- Случайные семена
if(iType == 0) {
// Очиска карты
vInitMap();
// Создание случайно расположенных начальных семян
for(i = 0; i < iNumSeeds; i++) {
// Установка начальной позиции семени
iSeedPos[i] = rand() % (g_iMapHeight * g_iMapWidth);
// Помещаем в позицию семени блок с изображением травы
g_iTileMap[iSeedPos[i]] = 17;
}
// Перемещение семени
for(i = 0; i < iNumUpdates; i++) {
for(j = 0; j < iNumSeeds; j++) {
iRandDirection = rand()%4;
// перемещаем семя вверх
if(iRandDirection == 0) {
iSeedPos[j] -= g_iMapWidth;
}
// Перемещаем семя вправо
else if(iRandDirection == 1) {
iSeedPos[j]++;
}
// Перемещаем семя вниз
else if(iRandDirection == 2) {
iSeedPos[j] += g_iMapWidth;
}
// Перемещаем семя влево
else if(iRandDirection == 3) {
iSeedPos[j]--;
}
// Если семя вышло за пределы карты,
// помещаем его в случайную позицию
if(iSeedPos[j] < 0 ||
iSeedPos[j] >= (g_iMapHeight * g_iMapWidth))
{
iSeedPos[j] =
rand() % (g_iMapHeight * g_iMapWidth);
}
// Помещаем в позицию семени блок с изображением травы
g_iTileMap[iSeedPos[j]] = 17;
}
}
}
// Отображение мини-карты
vRenderMinimap();
// Воспроизведение звука, сообщающего о завершении операции
PlaySound("bleep.wav",NULL,SND_FILENAME|SND_ASYNC);
}
В самом начале код равномерно разбрасывает по карте семена будущего ландшафта. Эти семена являются стартовыми точками будущих континентов, которые создаст код. В данном алгоритме не используется никаких шаблонов — семена размещаются абсолютно случайным образом. Справа от процедуры размещения семян показано, как будет выглядеть получившаяся в результате карта. Это не слишком впечатляюще, поскольку код лишь поместил блоки с изображением травы в стартовые позиции каждого семени.
Как только семена размещены на карте, код в цикле указанное число раз перебирает каждое из семян и случайным образом смещает его на один квадрат влево, вправо, вверх или вниз. В новую позицию семени также помещается блок с изображением травы. Вот так, медленно но верно, данный метод заполняет карту случайно расположенными блоками с изображением травы. На рис. 10.14 справа от процедур перемещения семени изображено, как карта постепенно обретает форму.
Есть еще пара вещей, отсутствующих на иллюстрации. Во-первых, перед началом создания ландшафта я вызываю функцию vInitMap() для очистки карты. Это требуется для того, чтобы перед созданием случайно расположенных блоков с изображением травы массив карты был приведен в исходное состояние. Во-вторых, на иллюстрации отсутствует проверка, гарантирующая, что семя не будет блуждать за пределами карты. Если семя выходит за границы карты, оно помещается в случайную позицию внутри карты и продолжает формировать изображение суши в новом месте. И последняя отсутствующая вещь — вызов функции отображения миникарты, показывающей обновленный ландшафт.