Виртуальная библиотека Delphi
- Название:Виртуальная библиотека Delphi
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Виртуальная библиотека Delphi краткое содержание
Виртуальная библиотека Delphi - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Возможно кто-то спросит: А зачем так много? Не достаточно ли 8 текстур, как на рисунке 2 — где трава пересекается с водой? Нет не достаточно. Ведь ситуации бывают разные. Окружающие ячейки могут быть не полностью забиты травой ( в данном случае землей ), и тогда понадобятся дополнительные текстуры.
Тогда может последовать другой вопрос: Почему так мало текстур? Где например текстуры когда вода с трех сторон окружена землей, и с четырех, и другие? Не следует ли предусмотреть все случаи?
И это правильный вопрос, но здесь все зависит от конкретной реализации алгоритма автоматического вычисления необходимой текстуры. В моем примере он реализован так, что остальные текстуры не нужны. Объясню наглядно:
1.Текстуры воды окруженные землей с двух противоположных сторон превращаются в базовую текстуру земли (в текстуру заполненную только землей). Соответственно то же самое происходит когда вода окружена с трех или четырех сторон.
Рисунок 5
2.Текстуры воды окруженные с двух уголков на одной стороне превращаются в текстуры полностью окруженные землей с одной стороны. (если уголки с трех сторон, то вода оказывается окружена полностью с двух сторон, если уголков 4, то вода превращается в землю совсем).
Теперь, я надеюсь, все ясно. С помощью применения подобной техники количество промежуточных текстур удалось уменьшить ровно в два раза! Это существенная экономия памяти, особенно если учесть, что типов земель будет больше. Кстати в WarCraft'e, если я не ошибаюсь, используется такой же набор текстур.
Ну хорошо, теперь давайте еще посчитаем. Для "слияния" двух земель нам понадобилось 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. Все текстуры имеющие в себе участок некоторого типа кроме переходного есть эта земля. То есть, к примеру, ячейки в первом круге – это вода.(см. Рисунок 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 означало бы цельную текстуру переходного типа — ЗЕМЛЯ.
Теперь давайте немного попишем:
PMap : PbyteArray; // указатель на матрицу содержащую нашу карту
WorldWidth, WorldHeight : Integer; // Ширина и высота карты в ячейках
Procedurecreatenewmap(worldwidth,worldheigth : integer);
Begin // Выделение памяти под матрицу
GetMem(pMap,WodrldWidth*WorldHeight);
// Заполнение этого участка нулями
FillChar(pMap,WorldWidth*WorldHeight,0);
End;
funciongetelement(x,y : integer):byte;
Begin // Получить значение ячейки
Result := pMap[y*WorldWidth + x];
End;
Procedureputelement(x,y : integer; index : byte);
Begin // Записать значение в ячейку
PMap[y*WorldWidth + x] := Index;
End;
Functiongetbaseindex(index : byte): byte;
Begin // Получить тип земли в виде номера(индекса)
Result := Index div 16;
End;
Functiongetadditionalindex(index : byte):byte;
Begin // Получить номер переходной текстуры
Result := Index mod 16;
End;
Вот. Вспомогательные функции мы написали, перейдем к рассмотрению технологии.
Посмотрите на Рисунок 6(б). Видно, что когда мы заменяем значение одной ячейки, эти изменения влияют, как на первый так и на второй круги ячеек. Возникает резонный вопрос: не случится ли такой ситуации, когда помещение на карту новой текстуры потребует перерисовки всей карты, так, словно кто-то бросил камень в воду? Если следовать принципам изложенным в этой статье, то не случится. Я проверял все варианты. Изменения касаются лишь первого и второго круга. Кто не верит, может проверить, посчитать, прикинуть, но это займет много времени. Теперь мы подходим к главному — по какому принципу рассчитывать новые значения изменяемых текстур. Возможно я Вас немного удивлю, но рассчитывать нам больше ничего не придется. Нам понадобится создать три массива (таблицы) 16 на 25 элементов, записать в них заранее расчитанные значения, а затем их считывать в ходе выполнения программы. Сейчас поясню.
Читать дальшеИнтервал:
Закладка: