netlib.narod.ru | < Назад | Оглавление | Далее > |
Большинство стратегических игр предоставляют игроку вид на мир со спутника, называемый мини-картой. В общем случае мини-карта показывает, как выглядит карта мира, если смотреть на нее из очень удаленной точки. Это очень полезная возможность как для игры, так и для редактора карт. У меня есть проект, в котором реализована данная функциональность. Взгляните на рис. 10.11, чтобы увидеть окно этой программы.
Рис. 10.11. Окно программы D3D_MapEditorPlusGold
Правильно, — это старый редактор карт, но теперь — золотое издание! (Я знаю, что название программы становится все более причуддливым, но по крайней мере я не называю ее MapEditor 2700+ или как-нибудь еще в этом роде!)
На рис. 10.11 вы видите редактор карт, но теперь в нижнем левом углу есть небольшое окно в котором отображается мини-карта. В действительности это большая карта мира, на которой каждый блок представляется одной точкой. Это позволяет мне отобразить полную карту мира, размером 100 x 100 блоков в окне размером 100 x 100 точек. Загрузите проект D3D_MapEditorPlusGold и я покажу вам изменения, необходимые для реализации отображения мини-карты.
Ход исполнения программы изменился не слишком сильно, но внесенные изменения надо проиллюстрировать. Пожалуйста, посмотрите на рис. 10.12, чтобы увидеть ход выполнения программы.
Рис. 10.12. Ход исполнения программы D3D_MapEditorPlusGold
На рис. 10.12 видно, как программа инициализирует DirectInput, клавиатуру, DirectGraphics, объекты интерфейса, блочную карту, панель инструментов и, наконец, окно мини-карты. Поскольку очень удобно, когда мини-карта размещается в собственном перемещаемом окне, я создаю отдельное окно специально для этой цели. Это делает функция 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().
Функция визуализации мини-карты работает точно так же как основная функция визуализации, перебирая в цикле блоки карты и выводя для каждого из них соответствующее изображение. Главное отличие заключается в том, что функция визуализации мини-карты проходит в цикле по всей карте, а не только по небольшой ее области, и, кроме того, при визуализации масштабирует изображение каждого блока до размера 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 | < Назад | Оглавление | Далее > |