Главная » 2D графика » Создание редактора карт в стратегиях типа WarCraft

RSS

Создание редактора карт в стратегиях типа WarCraft

Ну хорошо, теперь давайте еще посчитаем. Для «слияния» двух земель нам понадобилось 16 текстур. Но если к земле и воде добавить еще траву, то придется создавать также переходные текстуры для трава-земля и трава-вода. Это еще 32 текстуры. Добавим еще каменистую почву( надо же сделать карту разнообразнее). Еще 48 текстур. И так далее и так далее. А если мы хотим сделать несколько видов одной и той же текстуры( опять таки для разнообразия )? Количество текстур растет как на дрожжах. Что делать?

Но тут на помощь пришел опять-таки старый, добрый, затертый до дыр мышкой WarCraft. Никогда не замечали, что если в WarCraft’e, вернее в War Editor’e, «кладешь» воду на траву, то между травой и водой появляется прослойка земли? Вот и я заметил.

Текстура земли

Рисунок 6а

Текстура земли и воды

Рисунок 6б

Посмотрите на эти два рисунка. Из них видно, что вода граничит только с землей, трава тоже граничит только с землей. Земля в данном случае является «переходным» типом земли. Достаточно создать текстуры вода-земля, трава-земля, камни-земля, песок-земля и т. д. По 16 штук на каждую землю и все. Можно больше не беспокоится. Земли будут соединяться между собой через «переходный» тип земли. Спасибо WarCraft’у.

Итак, с количеством текстур и тем какими они должны быть мы разобрались, и вот наконец-то мы приступаем к самой реализации данной задачи.

Условимся, что:

  1. Ячейку с номером 12 я буду называть активной или текущей.
  2. Землю которой мы рисуем я также буду называть активной или текущей.
  3. Землю которая была прежде была в ячейке 12 я буду называть прежней.
  4. Ячейки под номерами 6,7,8,11,13,16,17,18 я буду называть первым кругом.
  5. Ячейки под номером 0,1,2,3,4,5,9,10,14,15,19,20,21,22,23,24 я буду называть вторым кругом.
  6. Все текстуры имеющие в себе участок некоторого типа кроме переходного есть эта земля. То есть, к примеру, ячейки в первом круге – это вода.

Пусть для данного примера у нас будет три типа земли: ВОДА, ТРАВА, КАМНИ. Плюс переходный тип – ЗЕМЛЯ. Нам понадобится 48 текстур. Почему 48, а не 64? – спросите вы, – ведь типов-то 4. Потому, что переходный тип и так есть в каждом из трех первых типов, в промежуточных текстурах.

Допустим, что текстуры у Вас будут храниться в компоненте ImageList, для нашего случая это удобнее всего. Разместим мы их следующим образом: за номером 0 будет располагаться цельная текстура воды, номера 1 – 14 займут промежуточные текстуры ВОДА-ЗЕМЛЯ (как на Рисунке 4), номер 15 займет цельная текстура ЗЕМЛИ. Следующий элемент ТРАВА займет номера 16 – 31 по тому же принципу, элемент КАМНИ займет номера с 32 – 47. Как Вы наверное заметили, номера 15,31,47 оказываются заняты одинаковыми цельными текстурами земли. Их можно сделать немного отличающимися друг от друга для обеспечения большего разнообразия, а затем выбирать случайным образом.

Введем базовые индексы типов земель. Пусть базовый индекс воды равен 0, базовый индекс травы равен 1, камней – 2. Тогда, узнав порядковый номер текстуры, мы можем выяснить какому типу земли она принадлежит, достаточно разделить целочисленным делением (Div) порядковый номер текстуры на 16. Если же мы разделим этот номер делением по остатку (Mod) на 16, то узнаем смещение или номер промежуточной текстуры внутри интервала номеров принадлежащего данному типу земли. Например, мы обратились к ячейке и получили номер 23. Поделив этот номер целочисленным делением на 16 получим 1. Это тип земли – ТРАВА. Поделив делением по модулю остатка на 16 получим 7. Это номер промежуточной текстуры.(См. Рисунок 4, только в данном случае была бы трава с землей) Заметьте, если бы вместо 7 мы получили 0, это означало бы цельную текстуру данной земли, 15 означало бы цельную текстуру переходного типа – ЗЕМЛЯ.

Теперь давайте немного попишем:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
PMap : PbyteArray; // указатель на матрицу содержащую нашу карту
WorldWidth, WorldHeight : Integer; // Ширина и высота карты в ячейках
 
Procedure CreateNewMap(WorldWidth,WorldHeigth : Integer);
Begin
  // Выделение памяти под матрицу
  GetMem(pMap,WodrldWidth*WorldHeight);
  // Заполнение этого участка нулями
  FillChar(pMap,WorldWidth*WorldHeight,0);
End;
 
funcion GetElement(x,y : Integer):byte;
Begin
  // Получить значение ячейки
  Result := pMap[y*WorldWidth + x];
End;
 
Procedure PutElement(x,y : Integer; Index : Byte);
Begin
  // Записать значение в ячейку
  PMap[y*WorldWidth + x] := Index;
End;
 
Function GetBaseIndex(Index : byte): byte;
Begin
  // Получить тип земли в виде номера(индекса)
  Result := Index div 16;
End;
 
Function GetAdditionalIndex(Index : byte):byte;
Begin
  // Получить номер переходной текстуры
  Result := Index mod 16;
End;

Вот. Вспомогательные функции мы написали, перейдем к рассмотрению технологии.

Посмотрите на Рисунок 6(б). Видно, что когда мы заменяем значение одной ячейки, эти изменения влияют, как на первый так и на второй круги ячеек. Возникает резонный вопрос: не случится ли такой ситуации, когда помещение на карту новой текстуры потребует перерисовки всей карты, так, словно кто-то бросил камень в воду? Если следовать принципам изложенным в этой статье, то не случится. Я проверял все варианты. Изменения касаются лишь первого и второго круга. Кто не верит, может проверить, посчитать, прикинуть, но это займет много времени. Теперь мы подходим к главному – по какому принципу рассчитывать новые значения изменяемых текстур. Возможно я Вас немного удивлю, но рассчитывать нам больше ничего не придется. Нам понадобится создать три массива (таблицы)16 на 25 элементов, записать в них заранее расчитанные значения, а затем их считывать в ходе выполнения программы. Сейчас поясню.

Поскольку в общей сумме у нас по максимуму может измениться 25 элементов на карте (Рисунок 6(б)), мы создадим вспомогательную матрицу 5х5, куда будем считывать с карты значения соответствующих ячеек. Затем мы изменим значения в этой матрице и поместим ее снова на карту откуда взяли.

В каждой ячейке может быть следующее значение:

Index + GroundIndex*16 , где

Index – число от 0 до 15 указывающее на номер переходной текстуры. GroundIndex – число от 0 до 2 указывающее на тип земли – ВОДА, ТРАВА, КАМНИ

Итак мы знаем номер лежащей в ячейке переходной текстуры (GetAdditionalIndex), мы также знаем номер этой ячейки в матрице 5х5. Этого вполне достаточно. Мы создадим массив-таблицу ширина которого равна количеству возможных переходных текстур 16, а высота равна количеству ячеек в матрице 5х5=25. Дальше мы действуем следующим образом: Считываем в матрицу 5х5 участок карты центром которого является ячейка в которую мы «кладем» новую землю, в ячейку 12 кладем цельную текстуру той земли которой мы рисуем. Затем для всех ячеек матрицы 5х5 кроме 12-ой делаем следующее: Поучаем номер переходной текстуры (GetAdditionalIndex) и обращаемся к таблице 16х25. Где номер переходной текстуры это положение ячейки таблицы 16х25 по горизонтали, а номер ячейки в матрице 5х5 это положение ячейки таблицы 16х25 по вертикали.

Координаты

Рисунок 7

На рисунке 7 , цифра 6 по горизонтали это GetAdditionalIndex от текстуры, которая прячется в матрице 5х5 в ячейке номер 17, а «Х» в красной клетке это тот самый новый номер для этой текстуры. Фактически смысл сводится к следующему: посмотрели какая была текстура – заглянув в таблицу, узнали какая стала.

Вы наверное спросите – а как узнать какие значения должны быть в таблице 16х25? Никак. Они рассчитываются в уме и записываются в таблицу ручками. Но вы можете не задумываться над этим, я уже рассчитал и записал их в своем примере. Смотрите в исходниках.

Кстати в тексте статьи я упоминал о том, что нам придется создать три таблицы 16х25. Я не оговорился. Дело в том, что у нас возможны три варианта, когда значения одной и той же ячейки в таблице должны быть разными:

1. Активная земля равняется прежней земле. Например, мы рисуем ТРАВОЙ, а в рассчитываемой ячейке тоже ТРАВА или ТРАВА с ЗЕМЛЕЙ.
2. Активная земля не равна прежней земле. Например, мы рисуем ТРАВОЙ, а в рассчитываемой ячейке ВОДА или ВОДА с ЗЕМЛЕЙ.
3. Рисуем переходным типом земли – ЗЕМЛЯ.
Если кому-нибудь еще что-то не понятно, то надеюсь после рассмотрения исходных текстов программы все встанет на свои места.

Страницы : 1 2 3 4