Как написать мод для minecraft на python
Python programming with minecraft
Our goal is to learn programming while having fun in Minecraft
0.1 Install Minecraft Java edition
Go to minecraft website download the Java Edition
0.2 Setup mincraft server
Go to Python download page, download and install Python 3.8 and up
0.4 Install mcpi Python module
input below script in the command line. (from start, search «cmd»)
0.5 Install a Python Editor
1. Get Start Python with Minecraft
1.1 Connect to the Minecraft server and get your position
Create a Python project folder, Download and save the sample1.py file to your python project folder
Use your faverate python editor to open the sample1.py file. When you install python, it come with a python editor call IDLE.j
1.2. Frequently used mcpi commands
1.2.1 Find your location
move player to north 100 block
set the a stone block beside the player
setblock with constants block.STONE.id
set special block which extra properties
get the block type id of the player stepping on
2 Learn Python With Minecraft
To use the code examples in this site, please make sure include the piece of code below before the sample codes
Minecraft coordinates are different than what we learn from geomestry. You need keep the picture below in mind when you do the minecraft coding.
For basic python syntax, pleas check Python syntax for details.
The missions/codes below will use print and command from minecraft api mcpi
for loops are traditionally used when you have a block of code which you wnat to repeat number of times.
For learnning how to use for loop, please visit Python For Loops
String and Intiger is different DataType, for detail please read Python Data Types. Below is the Data Types we possible will used in our class
example of get type of a variable:
The data you got form input is a string, we need convert to number before using as number. int(str) could do this job.
other way if you want change a int to string, you could use str(number)
To learn comdition please check Python If. Else
Booleans represent one of two values: True or False
For learn more and practic Boolean, please check Python Boolean
3 More Code Samples
3.1 Dropping the flowers when you move
Set a random flower on where the play is standing
3.2 Build a rainbow in the minecraft
code example: rainbow.py build a rainbow with colored wool on the player’s location
About
Introductions and Python Code examples for kids to learn python programming with minecraft. The Python code will run with a modified MCPI (Pi edition API Python Library) call `mcpi-e`, and a mincraft server call spigot with the RaspberryJuice plugin installed.
Как написать мод для minecraft на python
[Programming] [Перезалив] Пишем программы на Python. Урок 1.
Python — один из самых простых языков в мире, и активно используется для разработки игр, сайтов и даже мобильных приложений. Google почти весь построен на нем. Он развивает популярность все больше и больше и в конце случится взрыв. Python развивается больше и больше, и имеет огромное число своих юзеров, а также свое комьюнити. Язык прекрасно подойдет вам. если вы хотите научиться программить и не знаете на чем.
Прошу не пинать, так как я не супер-профи-мега-очень ни в Python, ни в составление новостей.
Давайте попробуем установить Python и написать первую простенькую программку.
Я пишу на PYTHON 2.7
Если вы сидите на Windows то открываем python.org и скачиваем с раздела Download нашу версию.
С Ubuntu же надо просто скачать Package в библиотеке пакетов Юбунды)
А вообще советую почитать на тему установки Python в инете, если у кого-то не получилось.
Вот, вы все установили и готовы писать вашу первую программу!
Открываем IDLE безинтерфейса и пишем:
Print — функция языка, и она пише в нашу консоль все, что мы вставили скобки, вы может поэкспереминтировать, вставив вместо Hello World любое русское или английское слово.
В каждом языке есть переменные. обычно они управляют всем миром языком.
Если быть точным, переменные — это ячейки памяти в которых что-то сохраняется.
Давайте попробуем сохранить в переменную некое случайное число.
Для этого нам потребуется модуль random
Во многих языках есть комментарии. В Python они тоже присуствуют, и сделаны они ради того чтобы нашему юному разрабу не забыть что он, собственно говоря, кодил.
Выделяются они в данном языке программинга красным цветом и пишутся на одной строке после #(Решетки).
А на этой простенькой программе мы заканчиваем кодить. Люди, я реально не знаю как еще лучше объяснить, простите если что-то не так.
Майнкрафт – одна из популярнейших и одна из самых продаваемых видеоигр за всю историю, собравшая вокруг себя огромнейшее игровое сообщество и предлагающая множество возможностей в обучении программированию.
Большое количество людей по всему миру используют Майнкрафт в образовательных целях: начиная с курсов в университетах, посвященных изучению и разработке искусственного интеллекта, заканчивая школами и летними лагерями. Эта популярная компьютерная игра также используется в изучении таких дисциплин, как химия, физика, математика, и даже история и многих других!
Во время занятий ребята:
Зачем ребенку изучать Python:
Занятия проводятся в игровом формате, который позволит детям не только научиться писать программы на Python, но также применять их в среде Майнкрафт и строить собственные миры!
Как мы понимаем, что учащийся освоил программу?
Во время обучения мы оцениваем как практическую сторону вопроса (как это сделать?), так и понимание темы (почему и зачем).
Ученики демонстрируют свои знания, решая задачи своим собственным способом, объясняя алгоритмы своими словами, помогая одногруппникам исправлять ошибки и создавая презентации по своим законченным проектам.
6000 рублей в месяц за 4 занятия
Продолжительность курса: 3 месяца
по субботам или воскресеньям, 1 раз в неделю
Есть такая замечательная игра — Minecraft. В целом очень напоминает Lego — можно строить из различных кубиков всё что душа пожелает. На Youtube можно найти много очень впечатляющих построек. Более того, строить можно совместно на специальных серверах.
В общем, в последнее время я довольно много играю в Minecraft
Одна из особенностей игры — процедурная генерация ландшафта. Т.е. в каком бы направлении Вы ни пошли, окружающий пейзаж будет создаваться по мере надобности. Общая площадь карты в Minecraft в несколько раз больше площади поверхности Земли. Сама карта подгружается частями — держать в памяти такое количество данных целиком просто бессмысленно. Недавно я от нечего делать решил написать парсер файлов Minecraft, чтобы сделать карту своей территории (я знаю что для этого есть инструменты, тот же c10t, но самому же всегда интереснее). Чтобы не было скучно, писать решил на Питоне
Вообще к Питону я приглядываюсь достаточно давно, и русскоязычное издание Learning Python лежит у меня под столом уже полгода. Но до сих пор ничего сложнее пробного hello world я на нём не писал. Парсер и картограф будут неплохим началом.
Формат файлов
Карта в Minecaft, как понятно из вышеприведённого описания, может быть очень большой. Поэтому она разбита на куски (chunks) размером 16 x 16 x 128 метров — этакие высокие колонны. Чанки сложены в директории по хешу их координат. В целом всё выглядит так: в корневой папке лежит основной файл level.dat, в котором хранится в т.ч. random seed для генерации ландшафта, и 64 папки верхнего уровня. В каждой из них находится по 64 папки второго уровня, в которых и лежат gzip-нутые файлы чанков.
Я уже писал что чанк отправляется в папку, соответствующую хешу его координат. Вот так можно вычислить этот хеш:
Код для преобразования в base36 взят с Википедии и допилен для отрицательных чисел.
Сам чанк (уже разархивированный) записан в специальном формате, называемом named binary tag — по сути, двоичный файл с именованными полями. В файле могут встречаться 11 видов стандартных тегов, последний из которых, compound, может содержать произволное количество других тегов (в том числе и типа compound). Стало быть, у нас будут структуры произвольного уровня вложенности.
Внутри самого файла, в поле с именем Blocks находится массив из 32768 байт — это и есть наша карта. На каджый блок, соответственно, отводится по одному байту, блоки идут вертикальными колоннами снизу вверх, с востока на запад и с севера на юг.
Кроме блоков в файле хранятся сущности, принадлежащие чанку — например, монстры. Но нас пока что это не интересует.
Разбор файла
Вначале я просто вырезал из файла байт за байтом, сверяясь со спецификацией формата, но когда освоился, переписал парсер нормально. Всего получилось 100 строк. Парсер целиком можно найти здесь. Основная функция выглядит так:
Каждый тег состоит из байта, указывающего на его тип, pascal-строки с именем тега и содержанием, которое зависит от типа тега. Нулевой тег — особый, ему не положено даже имя. Он завершает списки тегов внутри compound-тега.
Сначала мы читаем тип, если он ненулевой — читаем ещё и имя, и достаём содержание согласно типу. Чтение содержания для каждого типа я выделил в отдельную функцию (кроме типов 4,5 и 6, которые хранят длинные числовые значения в том или ином виде). Функция read_list_payload должна по хорошему называться read_list, но в принципе и так сойдёт.
Если мы прогоним этот скрипт по файлу какого нибудь чанка (предварительно распаковав его Winrar’ом или 7zip’ом), мы увидим что теги внутри compound-тега Level идут не в том порядке, который указан в спецификации. Т.к. все теги помечены именем, найти тег Blocks мы всё равно сможем, просто не получится взять его по заранее вычисленному смещению.
Вот примерная схема одного чанка:
Для обрамляющего compound-тега названия нет — на соответствуюшем месте просто записан нулевой байт (длина строки — 0).
Разбираем блоки
Получив наконец блоки, мы увидим что в результате python преобразовывает массив байт в строку. Нас это вполне устраивает. Теперь нам надо сориентироваться в их пространственном расположении. Для начала, Minecraft своеобразно подходит к определеению осей координат: ось Y у него вертикальна. Вики по Minecraft нам подсказывает, что в массиве блоков можно найти нужный элемент по такой формуле:
Находим тег с блоками в результатах разбора:
Система типов Питона мне пока немного непривычна, поэтому я использовал простые кортежи и списки. Хотя, по хорошему, теги надо было бы сохранять в виде словаря — их порядок нам всё равно не важен, а обращаться по имени тега было бы легче.
Вооружившись приведенной выше формулой, сделаем срез чанка на высоте, к примеру, 16. В обычном ландшафте это как раз самая толща породы внизу, с редкими пещерами и лавой.
Фиксируем высоту (координату y) на 16, и выводим получившуюся матрицу чисел 16 на 16. Потом смотрим в таблицу значений блоков, чтобы узнать что именно мы увидели.
Видим много камня и немного руды, сгруппированной в депозиты. Что ж, похоже на правду Теперь надо отобразить результат покрасивее.
Генерация карты
Чтобы сохранять изображения, нам потребуется Python Imaging Library. Устанавливается она без проблем. После установки можно будет приступить к генерации карты среза.
Изображения мы не задумываясь возьмём прямо из стандартного набора текстур Minecraft Идём в %appdata%\.minecraft, распаковываем minecraft.jar и достаём оттуда terrain.png. Выглядит он вот так:
Нам надо нарезать этот набор на аккуратные квадраты 16 на 16, и составить из них новое изображение. Вначале получаем тайлы:
Вот примерно так. Функция get_cropbox написана для вычисления координат вырезания и вставки. Это не все блоки, которые могут встретиться в игре, но с файлом текстур дополнить этот список Вы сможете и самостоятельно. Я пока остановлюсь на том что может встретиться под землёй.
Теперь, примерно так же как мы выводили текстовые значения блоков, мы заполняем изображение карты:
Здесь опять не все идентификаторы блоков, и если встретится что то незнакомое, на карте будет просто чёрный квадрат. И ещё тут надо помнить про систему координат, в частности, не путать y и z :). В результате этих манипуляций должен получиться PNG-файл со срезом карты:
Вот как то так Это конечно не полноценный картограф, но уже неплохое начало. На его основе можно например сделать маленький скрипт для поиска наиболее богатых рудой чанков или оптимальной глубины шахты.
Публикации сообщества
python and minecraft
Как говорил Остап Бендер: «Автомобиль это не роскошь, а средство передвижения». Сейчас это можно говорить о владении языками программирования и разработке роботов.
Изучение языков обычно более теоретизируется, т.е. подача материала превращается в стиль обучения, как в университетах с практическими абстрактными примерами, которые в свою очередь не сильно проясняют понимание алгоритмов и владение языком, особенно для школьников.
Кого учить?
В Германии были проведены исследования в области развития участков мозга при изучении языков программирования. Выяснилось, что при изучении языка программирования задействованы, в большей степени, те же участки мозга, которые отвечают за запоминания новых слов и изучение иностранных языков.
Я выбираю python
В результате, при переходе из школы в ВУЗ происходит разрыв шаблонов. В первую очередь резкий переход на текстовые языки программирования и уход в область изучения алгоритмов и высшей математики.
Minecraft
На сегодняшний день minecraft прочно связался с образованием. Появилась отдельное приложение и одноимённое сообщество minecraft education. Про них в этой статье я не буду писать, но данное направление имеет место быть для решения ряда образовательных задач.
Для изучения языков программирования python и java было разработано ещё одно приложение minecraft pi.
Эта среда в первую очередь разрабатывалась для микрокомпьютеров семейства raspberry pi. Данный minecraft устанавливается по умолчанию с операционной средой для микрокомпьютера и является бесплатным приложением.
Есть специальная локализация для windows и ios.
Для того, чтобы код на python мог интегрироваться в среду minecraft, используются различные локальные сервера. Их множество.
Один из них это Bukkit
Подключившись к локальному серверу, мы можем создавать программы на python и интегрировать их в среду minecraft.
Особенности программирования на python для minecraft
Главная специфика разработки программ для визуализации своего результата в minecraft опирается на пространство координат.
Так как это 3d игра, то все объекты имеют 3 координаты X, Y, Z
И это кладезь в области визуализации:
1. графиков математических функций, как двухмерных, так и трёхмерных.
2. построение фигур стереометрии и планиметрии.
Еще это наглядная демонстрация того, зачем нужна математика со всеми её разделами.
Например:
1. практическая реализация построения фигур с использованием декартовой, полярной и сферической системы координат
2. построение фигур с использованием тригонометрии
3. практическое закрепление понятий, что же такое вектор, матрица (массив), список, логика предикатов.
4. почему используются радианы, а не градусы.
5. зачем нужны трансцендентные и комплексные числа
И конечно же, это наглядная демонстрация тех или иных алгоритмов.
Всё это возможно применить и реализовать в среде minecraft с использованием языка python.
Правая ветка параболы
Данная парабола была построены с использованием всем известной формулы y =x^2, но с некоторыми поправками.
А именно масштаб и построение.
Код программы :
Построение параболы
Пример 2 График функции sin() через радианы
График sin() в радианах Построение sin() в радианах
Пример 3 График функции sin () c использованием напрямую с координаты
Как видим, данные показатели градусов были восприняты алгоритмом, как радианы и это наложило отпечаток на построение. Получились затухающие колебания sin И cos()
График sin() в градусах
Пример 4. Винтовая линия
Такая же особенность прослеживается, если строить винтовую линию.
Спираль Архимеда
Все эти примеры показывают влияние математики на мир.
Напоследок приведу пример применения цикла и условия для решения логических задач.
Конечно, изучение языка python и его библиотек не заканчивается использованием только среды minecraft
Это начальный уровень входа в достаточно сложную алгоритмику и поэтому подразумевает профессиональность учителя в области математики, программирования (заметьте, не информатики) и физики.
Надеюсь статья была вам полезна. Дерзайте и создавайте свои интересные проекты.
Стив пишет заклинания на Python. Обучение детей программированию в Minecraft
Я не имею в виду создание и использование модов, это слишком высокий уровень входа. Первые попытки были после знакомства с первым изданием книги Minecraft. Программируй свой мир и удачной настройки сервера Bukkit на домашней машине. На данный момент (начало 2021 г.) есть второе издание, ссылка как раз на него а также несколько похожих книг других авторов. Второе издание хорошо тем, что в нем исправлены ошибки в коде, которые были в первом, а также используется Python3 и более новая версия сервера. Вот тут на Хабре обзор первого издания от издательства Питер.
На странице издательства Wiley есть несколько видео для упрощения, самое первое как раз об установке и настройке сервера Bukkit, отдельно установка Python (не Anaconda, из простого дистрибутива), тьюториал подключения к запущенному серверу и запуска в нем HelloWorld из питоновского IDLE.
Библиотека mcpi была изначально написана для запуска python-скриптов в Майнрафте на Raspberry Pi. Версия Minecraft для Raspberry Pi распространяется бесплатно. Сейчас mcpi работает под Windows. Качать отдельно ее не надо, все входит в состав Bukkit-сервера.
Вертикальные и наклонные столбы
Воссоздаем Minecraft-подобную генерацию мира на Python
. используя диаграммы Вороного и много шумов Перлина/симплексных шумов
Прим. переводчика: стоит отметить, что непосредственно в Minecraft используются отличные от описанных ниже подходов — игра не использует диаграммы Вороного, а кроме двумерных шумов применяет также и трёхмерные (что, в частности, позволяет генерировать не только карту высот, но и пещеры)
Minecraft, самая продаваемая игра в мире, наиболее известная своими пикселизированными блоками и бесконечными мирами, содержит потрясающий процедурный генератор ландшафта — с пещерами, водоёмами, и даже различными биомами.
Процедурная генерация является важной частью компьютерной графики — она используется в основном в играх и в фильмах. Она помогает создавать случайные структуры, не вызывающие ощущения «машинного» стиля.
Также процедурная генерация играет важную роль в машинном обучении. Она позволяет генерировать такие данные, которые сложно собрать. Обучение моделей машинного обучения требует огромных датасетов, которые может быть затруднительно собирать и подготавливать. Генерацию данных процедурным образом можно легко адаптировать к требуемому типу данных.
В детстве мне нравилось играть в Minecraft, и мне всегда было интересно, как эта игра генерирует бесконечные миры. В данной статье я попытаюсь воссоздать это на Python.
Определения и ограничения
Для начала, определимся с тем, как будет генерироваться наш мир.
Мир является трёхмерным, дискретным (состоящим из блоков единичного размера), ограниченным по оси z в диапазоне от 0 до 255 и неограниченным по осям x и y.
Мир содержит биомы, каждый из которых охватывает большую площадь по горизонтали, и которые определяют характер местности в занимаемом биомом пространстве.
Мир содержит реки, озёра и океаны.
Каждый мир определяется зерном (англ. seed). Одно и то же значение зерна всегда приводит к генерации одного и того же мира.
Генерация миров
Чтобы упростить процесс генерации, мы разделим наш мира на чанки (англ. chunk — ячейка, кусок). Каждый чанк занимает пространство размером 1024×1024×256 блоков.
Каждый чанк генерируется отдельно. Это поможет нам сохранять и загружать мир, а также упростит задачу генерации мира по частям.
Прим. переводчика. В Minecraft также используется разбиение пространства на чанки, однако они имеют значительно меньшие размеры — 16x16x256 блоков (16x16x384 — начиная с версии 1.18)
Границы биомов
Первое, что нам нужно сделать — разделить мир на ячейки в плоскости xy, каждая из которых будет принадлежать определённому биому. Каждой ячейке мы назначим точку, обозначающую её центр.
Диаграмма Вороного
Диаграмма Вороного поможет нам разбить мир на ячейки по заданному множеству точек. Основная идея диаграмм Вороного заключается в том, что каждая точка плоскости принадлежит той ячейке, центр которой находится к ней ближе всего.
Движущаяся точка окрашивается в цвет ближайшей к ней неподвижной точки. Изображение автора.
Мы можем проделать это для каждой точки плоскости xy, чтобы построить диаграмму Вороного для этих трёх точек.
Анимированная диаграмма Вороного для 3 точек. Изображение автора.
Хотя такой подход и работает, он очень медленный, особенно когда количество точек велико.
Анимированная диаграмма для 20 точек. Изображение автора.
Диаграмма Вороного, построенная с помощью scipy.spatial. Изображение автора.
Класс Voronoi в scipy.spatial возвращает список вершин, регионов и рёбер, что будет полезно на следующих этапах.
Регион и ребро в диаграмме Вороного. Изображение автора.
Эти дополнительные точки помогают сформировать так называемую тесселяцию Делоне (прим. переводчика: также её часто называют триангуляцией Делоне).
Тесселяция Делоне поверх тесселяции Вороного. Изображение автора.
Алгоритм релаксации Ллойда
Теперь нам необходимо сгенерировать случайные точки, которые станут центрами ячеек.
Диаграмма Вороного для множества случайных точек. Изображение автора.
Как вы могли заметить, некоторые точки оказались слишком близко друг к другу. Это называется кластеризацией. Желательно, чтобы ячейки были распределены более равномерно.
Этот эффект становится более заметен, если мы уменьшим масштаб (или увеличим число точек):
Обратите внимание, как некоторые точки кластеризуются вместе, в то время как другие области остаются пустыми. Изображение автора.
Чтобы решить эту проблему, нам необходимо распределить точки дальше друг от друга.
Одним из способов решения этой проблемы является алгоритм релаксации Ллойда, который использует диаграмму Вороного, построенную по исходным точкам.
Идея алгоритма Ллойда заключается в том, чтобы построить диаграмму Вороного, а затем переместить каждую точку в центроид (геометрический центр) соответствующей ей ячейки. Данный процесс может быть повторён несколько раз.
Центроидом многоугольника является среднее от всех его вершин.
Вот диаграмма Вороного, в которой исходные точки отмечены синим цветом, а центроиды ячеек — красным.
Диаграмма Вороного с исходными точками (синие) и центроидами ячеек (красные). Изображение автора.
Далее мы можем заменить исходные точки (синие) центроидами (красными), и повторять этот процесс снова и снова.
Анимация алгоритма релаксации Ллойда. Изображение автора.
Это позволяет получить более привлекательное распределение случайных точек.
Шум Перлина/симплексный шум: зачем он нужен?
Чтобы построить случайный ландшафт, нам необходимо сгенерировать свойства, которые будут меняться случайным образом в пространстве — такие свойства, как высота, температура или количество осадков.
Попробуем сгенерировать случайное число в диапазоне от 0 до 255, для каждого блока в плоскости xy в нашем мире.
Это приведёт нас к следующему результату:
Слишком случайно. Изображение автора.
Что ж, это больше похоже на QR-код, нежели на мир в Minecraft.
Проблема заключается в том, что наши случайные величины не имеют под собой связной структуры. Каждое значение генерируется независимо и не имеет ничего общего с соседними.
Чтобы решить эту проблему, применим шум Перлина.
Шум Перлина. Изображение автора.
Шум Перлина был изобретён Кеном Перлином в 1983 году. В отличие от обычного случайного шума, он обладает внутренней структурой. Он больше похож на случайные паттерны, встречающиеся в природе (облака, распределение лесов).
Симплексный шум был также создан самим Кеном Перлином. Он имеет много преимуществ по сравнению с шумом Перлина. В наши дни шум Перлина и симплексный шум повсеместно используются в процедурной генерации.
Нам доступно 4 переменных, с которыми можно поиграть: scale (масштаб), octaves (число октав), persistence (персистентность), lacunarity (лакунарность). Я не буду объяснять, за что отвечает каждая из них, но предоставлю вам следующие гифки, которые я сделал, чтобы самому разобраться в этом.
Масштаб Число октав Персистентность Лакунарность
Шум Перлина с различными параметрами. Изображения автора.
«Правильность» ячеек — размываем границы
Несмотря на то, что сгенерированные для ячеек точки неплохо разнесены друг от друга, сами ячейки выглядят почти как правильные многоугольники.
Для устранения этого недостатка будем использовать шум Перлина. Для каждой точки мы выберем случайную точку поблизости и присвоим текущей точке вновь выбранную.
Для этого нам понадобится две карты шума, одна — для смещений по оси x, другая для оси y.
Анимация изменения величины шума границ. Изображение автора. Анимация изменения числа октав шума границ. Изображение автора.
Выбор биомов
В Minecraft представлено более 60 различных биомов, каждый со своими различными свойствами. Теперь, когда наш мир разбит на ячейки, нам необходимо присвоить биом каждой из них. Для этой цели мы будем использовать шум Перлина.
График температуры-осадков
Определим биомы, основываясь на двух параметрах: температуре и количестве осадков, используя график температуры-осадков. Так биомы обычно определяются в биологии окружающей среды.
«Влияние климата на наземные биомы», автор Navarras, Public Domain, CC0.
Вдохновляясь этой диаграммой, спроектируем наш собственный график температуры-осадков.
График температуры-осадков. Изображение автора.
Карты температуры и осадков
Теперь назначим каждой ячейке температуру и количество осадков, используя шум Перлина. Сгенерируем две карты, каждая из которых содержит значения шума для всех блоков в нашем чанке.
Карты температур и количества осадков. Изображение автора.
Выравнивание гистограмм
Чтобы лучше понять эту неравномерность, я построил одномерную гистограмму и потрясающую двумерную гистограмму карт температуры и количества осадков.
Одномерная (слева) и двумерная (справа) гистограммы карт температур и осадков. Изображение автора.
Как можно видеть, значения по краям дискриминированы. Чтобы устранить этот недостаток, выровняем наши значения.
Выровненная гистограмма становится плоской:
Выровненная одномерная (слева) и двумерная (справа) гистограммы карт температур и осадков. Изображение автора.
Поскольку мы выравнивали температуру и количество осадков независимо друг от друга, двумерная гистограмма не является полностью плоской.
Возможно, мы не хотим полностью сглаживать наши гистограммы. Чтобы иметь возможность управлять степенью сглаженности гистограмм, мы можем смешивать невыровненные значения с выровненными в некоторой пропорции.
Анимация выравнивания гистограмм. Изображение автора.
Теперь мы можем управлять тем, насколько выровнены наши значения.
Усреднение значений внутри ячеек
Квантование
Чтобы упростить работу со значениями температуры и количества осадков, преобразуем их в целые числа. Будем использовать np.uint8 в качестве типа данных для хранения этих значений.
Чтобы преобразовать значения карт, представленных выше, отобразим их на интервал [0, 255], и округлим к ближайшему целому.
Квантование не меняет то, как выглядит температура и количество осадков.
Теперь мы можем определить наш график температуры-осадков в виде изображения размером 256×256 пикселей:
График температуры-осадков. Изображение автора.
Карта биомов
Мы можем назначить каждой ячейке биом, используя график температуры-осадков, карту температур и карту осадков. Выполнив это для каждой ячейки, мы получим следующий результат:
Карта, окрашенная в цвета биомов. Изображение автора.
Карта высот
Каждая точка нашего двумерного мира имеет высоту. Чтобы построить карту высот, мы будем использовать карту шума.
Карта высот. Изображение автора.
Маска суши. Изображение автора.
Совместим эту маску с изображением выше:
Карта биомов с применённой маской суши. Изображение автора.
Чтобы визуализировать высоту, добавим затенение на карту:
Карта биомов с маской суши (слева), затенённая карта биомов с маской суши (справа). Изображение автора.
Пока что результаты выглядят многообещающе. Но сейчас высота не зависит от биома. Нам следует менять карту высот внутри каждого биома. Чтобы достичь этой цели, мы будем применять некоторую функцию к карте высот.
Детализированная карта высот
Будем теперь использовать 2 карты высот с различной степенью детализации. Для этого будем использовать различное число октав в шуме Перлина.
Вот две наших карты высот:
Резкая (слева) и размытая (справа) карты высот. Изображение автора.
Фильтрация карты высот
Мы будем работать с картой высот на суше (значения высоты в диапазоне от 0 до 1). Каждый биом будет использовать комбинацию двух карт высот (размытой и резкой) — и затем применять фильтр (функцию) к результату.
Идея применения фильтров основывается на инструменте Кривые (Curves) в Photoshop. Используем кубические кривые Безье, чтобы определить функцию, которую мы применим к карте высот.
Вот некоторые примеры фильтров:
Пустыня (прим. переводчика: синий график справа — исходный срез высот, оранжевый — после применения фильтра) Горы (прим. переводчика: синий график справа — исходный срез высот, оранжевый — после применения фильтра)
Создадим и настроим фильтр для каждого биома.
Пустыня, саванна и тропический лес. Изображение автора. Тундра, сезонный лес и дождевой лес. Изображение автора. Умеренный лес, умеренный дождевой лес и бореальный лес. Изображение автора.
Чтобы применить эти фильтры к нашей карте высот, мы будем использовать маски. Маска это карта, содержащая 1 в областях, принадлежащих некоторому биому, и 0 в остальных областях.
Маска биома. Изображение автора.
Если мы будем использовать жёсткую маску, у нас будут огромные перепады высот (на границах биомов — прим. переводчика). Поэтому применим размытие к маскам перед использованием. Также удалим океан с этой карты (умножив её на маску суши), чтобы применить фильтры только к суше.
Размытая маска биома (слева), только суша (справа). Изображение автора.
Применим фильтры каждого биома к карте высот, пользуясь масками выше. Получим следующие результаты:
До и после
Итоговые результаты в 3D
Используя Blender, мы можем отрендерить эти карты в 3D. Используем карту высот в модификаторе «Displace» в Blender.
Рендер карты высот с окрашиванием в зависимости от биома. Сделано при помощи Blender. Изображение автора. Рендер карты высот с окрашиванием в зависимости от биома. Сделано при помощи Blender. Изображение автора. Рендер карты высот с окрашиванием в зависимости от биома. Сделано при помощи Blender. Изображение автора.
Реки и озера
Границы
Добавим реки на границах между биомами. Во-первых, нам понадобится вычислить границы между биомами.
Для этой цели мы переберём все точки на карте. Если у некоторой точки все её соседи принадлежат тому же биому, то она не лежит на границе. Если среди её соседей больше одного типа биома, то она является частью границы.
Иллюстрация пограничного пикселя. Изображение автора. Пример границы. Изображение автора.
Применяя этот подход к нашей карте биомов, получим следующие результаты.
Карта биомов (слева) и рек (справа). Изображение автора.
Можно управлять шириной рек, изменяя размер окрестности, содержащей соседние точки.
Реки различной ширины. Изображение автора.
Будем использовать 2 различных разновидности рек: биомные реки и ячеечные реки. Биомные реки широкие и размещаются на границах биомов, в то время как ячеечные реки меньше и размещаются на границах ячеек. Затем используем маску суши, чтобы ограничить реки сушей.
Реки также будут ограничены лишь средней и низкой высотой над уровнем моря.
Реки. Изображение автора.
Прим. переводчика. Честно говоря, на мой взгляд, тут у автора получилось что-то очень странное в отношении рек.
Используем эту маску рек чтобы изменить карту высот. Размоем эту маску рек, а затем применим исходную маску рек к полученному результату. Таким образом получится карта с большими значениями в серединах рек, которые плавно уменьшаются к берегам.
Вот сравнение маски рек с размытой и маскированной маской рек.
Маска рек. Изображение автора. Боковое сечение маски рек. Изображение автора.
Используем эту карту, чтобы «прорезать» реки в карте высот.
Карта биомов (слева) и карта биомов с реками (справа). Изображение автора.
Деревья и растительность
Чтобы добавить деревья на нашу карту, используем алгоритм релаксации Ллойда, описанный ранее. Этот метод сэмплирования помогает генерировать случайные точки, разнесённые друг от друга.
Прим. переводчика: для получения равномерно разнесённых точек также неплохо подходит алгоритм сэмплирования диском Пуассона (Poisson Disc Sampling)
Будем создавать множества деревьев различной плотности в зависимости от биома.
Различные уровни плотности деревьев. Изображение автора.
Скомбинируем множество деревьев с масками биомов и маской суши, чтобы заполнить биомы деревьями. Каждый биом имеет различную плотность и, разумеется, различные типы деревьев.
Карта биомов с деревьями. Изображение автора.
Мои навыки владения Блендером не позволяют мне визуализировать карту с деревьями в 3D 🙁
Исходный код
Вот ссылка на Jupyter-ноутбук, содержащий все описанные в статье шаги в виде кода.
Предупреждение: Код очень запутанный и незадокументированный.
Заключение
Процедурная генерация является мощным инструментом в компьютерной графике. Она позволяет сгенерированному контенту выглядеть случайным, но в то же время художественным и структурированным. Как было сказано ранее, это можно использовать в машинном обучении для создания датасетов, покрывающих те области, которые дорого или затруднительно покрыть с помощью данных, собранных в реальном мире.
Эта статья была лишь забавным проектом, над которым я хотел поработать уже больше года. В нём ещё многого не хватает. Например, мне нужно создавать пещеры под землёй, деревни, а также придумать алгоритм, способный бесшовно соединять соседние чанки.
Источники вдохновения
Я вдохновлялся многими статьями, когда писал мою. Если вам понравилась эта статья, то вам определённо захочется прочитать и эти тоже: