Разобравшись с моделями для 3D-ландшафтов в прошлом выпуске, перейдем к следующему этапу — созданию редактора 3D-карт. Другими словами, научимся наполнять пустой ландшафт различными игровыми объектами.
Постановка задачи
Маг. |
Обратимся к уже известной нам игре «Обелиск» и перенесем ее в 3D.
Код этого примера и все необходимое вы найдете на нашем диске.
Гном-воин. |
Поговорим кратко о правилах игры.
Цель битвы — захват нескольких обелисков, расставленных по карте. Перед сражением мы расставляем свои войска.
Дружина одной стороны («красные») состоит из 6 гномов, 4 лучников, 2 рыцарей, 2 магов и 1 призрака.
Другая сторона («зеленые») представлена 6 гоблинами, 4 орками, 2 орками-наездниками, 2 шаманами и 1 демоном. Кроме них, на карте бывает разная нейтральная нечисть.
Далее с каждым ходом игрок имеет право сделать по одному действию каждой фигуркой. Действие состоит из движения и атаки — в произвольном порядке.
Характеристики бойцов представлены в таблице.
Характеристики бойцов | ||||||
Боец | Передвижение | Хиты | Дальнобойность | Повреждения | Защита | Способности |
Гном | 4 | 8 | 1 | 7 | 2 | - |
Лучник | 4 | 5 | 7 | 5 | 1 | - |
Рыцарь | 3 | 15 | 1 | 9 | 4 | Лечение, рыцарский удар |
Маг | 3 | 12 | 5 | 6 | 0 | Огненный шар |
Привидение | 4 | 7 | 2 | 5 | 5 | Регенерация |
Нейтрал | 6 | 30 | 2 | 12 | 5 | Полет |
Гоблин | 4 | 8 | 1 | 7 | 2 | - |
Орк | 4 | 5 | 7 | 5 | 1 | - |
Орк-наездник | 3 | 15 | 1 | 9 | 4 | Лечение, рыцарский удар |
Шаман | 3 | 12 | 5 | 6 | 0 | Огненный шар |
Демон | 4 | 7 | 2 | 5 | 5 | Регенерация |
Лечение — это право раз за бой вылечить соседнего воина (кроме призрака) до полного здоровья. Рыцарский удар — право раз за игру нанести тройные повреждения. Огненный шар — атака мага снимает хиты не только с непосредственной цели, но и с окружающих квадратов. Регенерация — восстановление по 1 хиту за ход. Полет — право перемещаться через препятствия.
Игра идет в многопользовательском режиме, в варианте Hot Seat (игра с одного компьютера, ходы по очереди). После хода игроков делают свой ход нейтралы, атакуя любого противника в радиусе 7 клеток. Позже разработаем некий AI, чтобы играться с компьютером.
Партия заканчивается, когда одна из сторон либо захватывает более половины присутствующих на карте обелисков, либо гибнет полностью.
Карта задана изначально в редакторе карт. На ней расставлены обелиски, нейтралы и другие игровые объекты.
Одна из основных задач, которая встает перед нами, — это создание редактора для игровой карты, который позволял бы гибко и быстро задавать начальное местоположение игровых объектов, удалять их, перемещать, сохранять и восстанавливать текущее состояние карты. Конечно, это все можно сделать вручную с помощью API нашего движка.
Добавляем объект на ландшафт карты |
// координата y — высота — не нужна, она определяется автоматически World.AddObjOnRectMap(true, 1, 5,0, MAN_SPEED, MAN_MESH_ID, 1, -1, 0, true); |
Но гораздо удобнее высадить лес или перенести стрелка на 20 позиций вправо в визуальном редакторе, чем делать это вручную, копаясь в коде.
Далее готовая карта скармливается движку игры, созданному на базе LKICreator3D, и начинается собственно игра.
Функции редактора
Внешний вид редактора карт. |
Редактор позволяет:
размещать игровые объекты заданных типов;
управлять объектами, которые уже находятся на карте (выделять, двигать, поворачивать, удалять);
сохранять и восстанавливать текущее состояние карты со всеми объектами на ней.
Задавать параметры объектов, не связанные с их местоположением на карте — такие как скорость, сила, здоровье и т.д. — будем программно, непосредственно в игровом мире. В принципе, можно и их вынести в редактор, но они изменяются не часто, и особой необходимости в этом нет.
Добавление нового объекта на карту — что может быть проще с точки зрения пользователя?
Выбираем тип объекта в панели инструментов, выбираем место на карте, щелкаем мышью — и если выбранный объект может быть помещен в выбранное место (не пересекается с другими объектами на карте, ландшафт подходящий) — то он появляется на карте.
Нужно откорректировать местоположение объекта на карте? Выбираем нужный объект. Щелкаем на нем мышью, а дальше либо вращаем его, либо двигаем по карте в нужное место. Можно также удалить объект, если он нам разонравился.
Сегментация карты
Как мы уже знаем, карта, а точнее ландшафт, физически — модель в формате DirectX, представленная в виде полигональной сетки, выстроенной по сгенеренной карте высот. То есть физически карта уже разбита на сегменты матрицы высот. Эти сегменты используются для определения высоты ландшафта в произвольно выбранной на нем точке. Однако для таких целей, как оценка пути, видимости объектов, достижимости цели и т.д., физические сегменты вряд ли подходят, так как они слишком малы и жестко привязаны к физической модели ландшафта карты.
Вместо них предлагается использовать разбиение на логические сегменты. Размер логического сегмента может быть выбран гибко, вне зависимости от размера физического сегмента, а исходя из потребностей движка игры. Например: стоит задача оценить магическую атаку колдуна глубиной в 10 единиц расстояния по кругу от него. Определять пораженные цели в лоб слишком накладно, так как объектов на карте может быть много. Горазда эффективнее оценить, какие объекты поражены, по их принадлежности к логическим сегментам, попадающим в зону действия удара. Такие сегменты определяются очень легко — они находятся по соседству с сегментом, к которому принадлежит колдун. А переходы объектов из сегмента в сегмент можно определять только при их перемещениях, что, опять-таки, сокращает время на проверку.
Карта в 3D по сравнению с 2D
Вообще говоря, хотя карты в 3D намного симпатичнее, чем на плоскости, но и забот разработчику игры они добавляют достаточно. Возьмем несколько типовых задач — определение видимости объекта, движение объекта к указанной на карте цели, следование объекта складкам рельефа при передвижениях, задание непроходимых участков рельефа. На плоскости эти задачи сводятся к нахождению соседей определенных сегментов карты и оценке параметров сегментов (проходимости). В пространстве все не так тривиально. Казалось бы, ну, добавилась еще одна ось измерений, и что с того?
Однако теперь для того, чтобы определить видимость одного объекта со стороны другого, нужно не просто посчитать, сколько между ними укладывается сегментов, и определить, каковы их параметры, а определить луч взгляда и найти, не пересекается ли он с какой-либо выпуклостью рельефа. Это повышает порядок числа операций, связанных даже с грубым решением задачи — то есть неточным, но удовлетворительным.