the_JaGGer:
Процедурная Генерация для начинающих
Урок написан abhilash2863
(Terminateblog.wordpress.com)
"Процедурная генерация это широко распространенный термин в разработке контента; это относится к тому контенту, который создается посредством какого-либо алгоритма, а не вручную. Очень часто это относится к компьютерной графике, приложениям и дизайну видео-игр" - из Википедии.
В этом уроке мы узнаем об основе процедурной генерации. Сначала мы узнаем как использовать массивы(arrays), а также как нарисовать карту используя их. Затем используя довольно простой алгоритм, мы процедурно сгенерируем пещеры, которые могут быть использованы в roguelike-играх.
Массивы
Массивы - это объекты которые могут быть использованы чтобы хранить множество значений. Construct поддерживает 3 типа масивов - 1D, 2D, и 3D массивы.
Несмотря на то, что массивы невидимы, вы можете представить их примерно так:
Одномерные массивы имеют только один атрибут: ширину. Но Двумерные массивы имеют ширину и высоту. Ячейки называются элементами, в которых хранятся значения. Каждый элемент имет свой собственный адрес/индекс.
В 1D-массиве первый элемент имеет индекс 1, второй 2 и так далее.
В 2D-массиве первый элемент имеет индекс [1,1], второй [1,2] и так далее. Индексы обозначают примерно следующее - [Текущий ряд, Текущая Колонка].
Я опускаю 3D-массив потому что мы не будем его использовать, да и нарисовать его сложно. Но вы можете представить кубик Рубика, который выглядит как 3D-массив. Трехмерный массив имеет еще один атрибут, который называется "глубина" (depth).
В Construct массивы начинаются с индекса 1, но обычно в языках програмированния, таких как С, С++, С#, Phyton они начинаются с 0, так что будте внимательней с этим.
Что ж, этих знаний достаточно.
Откроем Construct (Я использую r1.2)
Правым кликом на слое откроем контекстное меню и выберем "Insert an Object". Выбираем Array и нажимаем Insert. Массив не будет отображаться на слое. Такие объекты называются non-layout объекты.
Выберем массив и посмотрим на его свойства:
В данный момент это одномерный массив с шириной 10. Но нам нужен двумерный массив, поэтому сменим высоту на 10.
Теперь, используя массив мы нарисуем карту, содержащую два типа блоков - Ground(земля) и Wall(стена). Массив будет содержать информацию о карте, каждый его элемент будет представлять блок. Если элемент будет иметь значение 0, то это будет Стена, но если значение элемента будет содержать 1, то это уже будет земля.
Так как массив невидим, то нам нужно что-нибудь, что будет представлять его на слое. Вставим спрайт на слой, в открывшемся окне редактора изображений окрасим всю площадь в синий цвет. Закроем редактор и сохраним изменения. Назовем спрайт "ground" и изменим ширину и высоту до 16. Должно получиться как-то так:
Теперь вставим другой спрайт, но в этот раз зальем его зеленым цветом и назовем его "wall", ширина и высота у него будет также 16х16. Теперь у нас есть 2 спрайта, которые выглядят так -
Каждый спрайт будет представлять блок. Итак, массив и его отображение будут выглядеть примерно так -
Теперь научимся как управлять массивом чтобы нарисовать карту используя его. Идем в редактор событий и вставим новое действие. Выберем System Object и используем условие "Start of layout". Добавим под событие: выберем массив и выберем "For each Element". Затем кликнем на "New Action" и снова выберем массив, а затем выберем действие "Set value at X,Y", после чего нажимаем next. Затем изменяем значение Х на "Array.CurrentX", а значение Y на "Array.CurrentY". Значение Value изменим на "int (random(2.".
Выражение "int" используется чтобы получить 0 или 1, чтобы значение не были 0.23, 0.58 и типа того.
Итак, теперь у нас есть событие, которое присваивает каждому элементу 0 или 1. Теперь у нас есть случайная карта.
Заметьте: Когда вы используете условия "for", "repeat", "for each element" (условие, которые всегда выполняются) всегда используйте "Start of layout" или "Trigger once" или другие условия, которые не дают событию повторять себя, тем самым радикально понижая FPS.
Следующий шаг. делаем карту видимой.
В условии "Start of layout" добавим еще одно подсобытие "For each" (Смотрите не добавьте его в предыдущее условие "For each")
Теперь добавим подсобытие в только что созданный "For each". Кликаем на Массив и выбираем "Compare value at X,Y". Нажимаем next.
Теперь пишем следующее:
Теперь условие будет проверять равно ли значение элемента 0(ноль) или нет. Теперь жмем по "+New Action", выбираем System Object > Create Object. Вводим следующие настройки :
В окнах X-Coordinate и Y-Coordinate мы умножили текущие X и Y, чтобы блоки не перекрывали друг друга.
Теперь сделаем тоже самое для блоков земли. Хороший метод когда события одинаковы - это просто скопировать нужные события, вставить их и изменить необходимые значения.
Теперь все готово, Нажимаем Preview the layout чтобы посмотреть на карту.
Возможно, то что вы увидите, будет отличаться. Все потому-что это. случайно. Если у вас получилось тоже самое, то возможно вам стоит сыграть в лотерею, потому что шанс того, что карты будут одинаковы 1 к 1267650600228229401496703205376.
Но все же, это не совсем Процедурная генерация, сейчас это больше случайная генерация, но целью урока было познакомить вас с массивами и как можно ими управлять.