netlib.narod.ru< Назад | Оглавление | Далее >

Отображение мини-карты

Большинство стратегических игр предоставляют игроку вид на мир со спутника, называемый мини-картой. В общем случае мини-карта показывает, как выглядит карта мира, если смотреть на нее из очень удаленной точки. Это очень полезная возможность как для игры, так и для редактора карт. У меня есть проект, в котором реализована данная функциональность. Взгляните на рис. 10.11, чтобы увидеть окно этой программы.


Рис. 10.11. Окно программы D3D_MapEditorPlusGold

Рис. 10.11. Окно программы D3D_MapEditorPlusGold


Правильно, — это старый редактор карт, но теперь — золотое издание! (Я знаю, что название программы становится все более причуддливым, но по крайней мере я не называю ее MapEditor 2700+ или как-нибудь еще в этом роде!)

На рис. 10.11 вы видите редактор карт, но теперь в нижнем левом углу есть небольшое окно в котором отображается мини-карта. В действительности это большая карта мира, на которой каждый блок представляется одной точкой. Это позволяет мне отобразить полную карту мира, размером 100 x 100 блоков в окне размером 100 x 100 точек. Загрузите проект D3D_MapEditorPlusGold и я покажу вам изменения, необходимые для реализации отображения мини-карты.

Ход исполнения программы изменился не слишком сильно, но внесенные изменения надо проиллюстрировать. Пожалуйста, посмотрите на рис. 10.12, чтобы увидеть ход выполнения программы.


Рис. 10.12. Ход исполнения программы D3D_MapEditorPlusGold

Рис. 10.12. Ход исполнения программы D3D_MapEditorPlusGold


На рис. 10.12 видно, как программа инициализирует DirectInput, клавиатуру, DirectGraphics, объекты интерфейса, блочную карту, панель инструментов и, наконец, окно мини-карты. Поскольку очень удобно, когда мини-карта размещается в собственном перемещаемом окне, я создаю отдельное окно специально для этой цели. Это делает функция vCreateMinimap().

Функция vCreateMinimap()

Функция создания мини-карты вызывается приложением только один раз во время инициализации. Функция создает окно для мини-карты и размещает его в нижнем левом углу главного окна редактора. При вычислении координат этого окна я учитываю местоположение и размер главного окна редактора и размер мини-карты. Вот код, который создает окно:

// Создание окна мини-карты
hWndMinimap = CreateWindowEx(
   WS_EX_LEFT|WS_EX_TOPMOST|WS_EX_TOOLWINDOW,
   "Minimap", "Minimap",
   WS_BORDER | WS_VISIBLE | WS_MINIMIZEBOX,

   rcWindow.left + 10, rcWindow.bottom + g_iYOffset - 140,
   100, 100, hwnd, NULL, hinst, NULL);

Приведенный выше код не слишком гибок, поскольку я жестко запрограммировал его для мини-карты размером 100 х 100 точек. Впрочем, ничто не мешает вам изменить эти значения, чтобы приспособить окно для отображения мини-карты другого размера.

Теперь, когда у вас есть окно мини-карты, необходим код, который будет отображать саму мини-карту. Этим занимается функция vRenderMinimap().

Функция vRenderMinimap()

Функция визуализации мини-карты работает точно так же как основная функция визуализации, перебирая в цикле блоки карты и выводя для каждого из них соответствующее изображение. Главное отличие заключается в том, что функция визуализации мини-карты проходит в цикле по всей карте, а не только по небольшой ее области, и, кроме того, при визуализации масштабирует изображение каждого блока до размера 1 х 1 пиксел. Вот код, выполняющий эту, достойную Геракла работу:

void vRenderMinimap(void)
{
   RECT   rectSrc;
   RECT   rectDest;
   int    iX;
   int    iY;
   int    iCurTile;
   int    iBufferPos;

   // Очистить вторичный буфер, заполнив его синим цветом
   g_pd3dDevice->Clear(0, NULL,
                D3DCLEAR_TARGET,
                D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
   // Начинаем отображение сцены
   g_pd3dDevice->BeginScene();

   // Визуализация мини-карты
   // Сверху вниз
   for(iY = 0; iY < g_iMapHeight; iY++) {
      // Справа налево
      for(iX = 0; iX < g_iMapWidth; iX++) {
         // Вычисление смещения в буфере
         iBufferPos = iX + (iY * g_iMapWidth);
         // Получаем требуемый блок
         iCurTile = g_iTileMap[iBufferPos];
         // Отображаем блок
         vDrawInterfaceObject((iX),
                      (iY),
                      (float)1,
                      (float)1,
                      iCurTile);
      }
   }
   // Завершаем сцену
   g_pd3dDevice->EndScene();
   // Исходный прямоугольник
   rectSrc.top    = 0;
   rectSrc.bottom = g_iMapHeight;
   rectSrc.left   = 0;
   rectSrc.right  = g_iMapWidth;
   // Прямоугольник места назначения
   rectDest.top    = 0;
   rectDest.bottom = g_iMapHeight;
   rectDest.left   = 0;
   rectDest.right  = g_iMapWidth;
   // Представляем результат
   g_pd3dDevice->Present(&rectSrc, &rectDest, hWndMinimap, NULL);
}

Я отметил наиболее интересные части функции полужирным курсивом. Обратите внимание, что при выводе я устанавливаю размер каждого блока равным 1 х 1 пикселу. Благодаря этому при отображении мини-карты происходит масштабирование каждого блока до размеров единственной точки. Важно заметить, что при этом точка представляет общий цвет блока, поскольку это масштабированное представление, а не замещающая текстура. Что такое замещающая текстура? Один из методов рисования мини-карты заключается в том, что каждому типу блоков назначается представляющий его цвет. Например, вода может изображаться квадратами синего цвета, земля — квадратами зеленого цветаа постройки — черными квадратами. В этом случае не надо выполнять масштабирование блока, а достаточно заменить блок на точку с цветом, соттветствующим функциональному назначению данного блока в игре. Лично я предпочитаю метод масштабирования, поскольку он позволяет получить более точное представление карты и обходится без дополнительного кода для замещения текстур.

СОВЕТ
Если вы хотите получить мини-карту более крупного масштаба, надо только изменить размер окна мини-карты и размер блоков в цикле визуализации. Побробуйте сделать это!

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz