Alvaros
.
- Регистрация
- 14.05.16
- Сообщения
- 21.452
- Реакции
- 101
- Репутация
- 204
Процедуральное искусство — это подвид генеративного искусства. Как и любая тема в программировании, она может выглядеть пугающей, если вы никогда не сталкивались с ней раньше. Мне всегда это было интересно, так как я люблю находить новые методы творческого использования программирования. Более того, я думаю, каждый может высоко оценить и понять идею творческой работы, которая в прямом смысле создает саму себя.
Что такое процедуральное искусство?
Процедуральное искусство — это результат работы системы, а не человека, которая принимает свои собственные решения относительно того, как должно выглядеть итоговое произведение. Программа может быть простой, как, например, кусок кода на Python, но внутри у нее должны быть логика, правила и некое свойство хаотичности.
Это несложно — придумывать правила и ограничения в программировании. Однако, чтобы заставить все эти правила создать что-то интересное, надо использовать различные подходы, что может быть сложно с непривычки. Хорошим примером такого подхода может служить игра «Жизнь» Джона Конвея.
Игра «Жизнь» Джона Конвея
You must be registered for see links
— это популярный набор из четырех примитивных правил, определяющих «рождение» и «смерть» каждой ячейки в системе. Каждое из этих правил влияет на развитие системы в целом. Несмотря на то, что правила несложные и просты для понимания, все равно в результате начинают быстро возникать сложные модели и в конце получается интересный результат.Правила могут создать базис для чего-то интересного, но результат даже такого захватывающего процесса как «Жизнь» — предсказуем. Так как четыре базовых правила являются постоянными и неизменными для каждой новой генерации, для получения непредсказуемых результатов надо внедрять рандомизацию переменных для ячеек в самом начале. Случайная матрица делает каждую генерацию уникальной без изменения правил построения модели.
Лучшие примеры процедурального искусства — это те, которые совмещают в себе предсказуемость и случайность одновременно, что также уменьшает вероятность точного повторения каждого отдельного варианта произведения.
Почему нужно попробовать это?
Есть много вариантов, чем заняться в качестве своего сайд-проекта, и процедуральное искусство выглядит как не самый очевидный вариант. Тем не менее, если вы решите работать над таким проектом, то можете рассчитывать на такие преимущества:
- Опыт. Процедуральное искусство — это просто еще одна возможность совершенствовать некоторые ваши новые и старые навыки. Вы сможете отработать навыки в алгоритмах, структурах данных и даже попрактиковаться в новых для себя языках.
- Видимый результат. В мире программирования мы редко видим, как наша идея воплощается в осязаемом виде (или по крайней мере это не работает со мной). В данный момент у меня есть несколько плакатов в гостиной, которые демонстрируют следы моего процедурального искусства, и мне приятно, что в основе него лежит программирование.
- Интересно для других. У нас у всех есть опыт объяснения попытки объяснить суть личного проекта кому-то, возможно, даже во время интервью. В программировании нет простого способа объяснить сложность проекта и итоги его реализации. Процедуральное искусство говорит само за себя, и большинство людей будут впечатлены вашими разработками и творениями, даже если они не могут полностью понять используемые методы.
С чего вы должны начать?
Начало работы с процедуральным искусством – это то же самое, что и начало любого другого проекта. Самый ключевой шаг – это придумать идею или найти эту идею для ее дальнейшего развития. Как только у вас появилась цель в голове, вы можете начинать работать над технологией, необходимой для достижения цели.
Большинство моих проектов процедурального искусства были выполнены на Python. Это довольно простой язык, который легко освоить, и у которого есть несколько отличных пакетов, упрощающих обработку изображений, например — Pillow
You must be registered for see links
. Чтобы вам не пришлось долго разбираться, я написал кое-какой код ниже, чтобы вы могли использовать его в своих целях.
Спрайт-генератор.
Идея проекта возникла, когда я увидел пост про создание генератора спрайтов, написанный на Javascript. Программа создавала небольшие 5х5 пикселей спрайты со случайным цветовым набором, а ее результат был похож на разноцветных космических захватчиков из игры Space Invaders.
Я хотел попрактиковаться в обработке изображений на Python, поэтому решил просто попытаться воссоздать эту концепцию самостоятельно. Еще я подумал, что могу расширить ее изначальный размер, поскольку первоначальный проект был очень сильно ограничен в размере спрайтов. Я хотел задавать в качестве параметров не только размер спрайтов, но и их количество и даже сам размер изображения.
Посмотрите на два разных результата, которые я получил в итоге исполнения одного и того же кода:
7x7–30–1900
43x43-6-1900
Эти два изображения совсем не похожи друг на друга, но они оба являются результатом одной и той же программы. Не говоря уже о том, что благодаря большому количеству параметров у изображения и высокой вариативности, существует очень высокий шанс того, что даже при одних и тех же принципах расчета, эти изображения навсегда останутся уникальными для этой вселенной. Мне это нравится.
Настройка среды разработки
Если вы хотите начать экспериментировать с генерацией спрайтов, сначала нужно подготовить программную среду. Настройка среды для Python может быть небанальной задачей. Если вы раньше никогда не работали с Python, то вам, вероятно, придется скачать
You must be registered for see links
. У меня были проблемы с настройкой окружения, поэтому, если у вас возникнут проблемы, можете сделать то же, что и я, и попробовать пакетную установку через
You must be registered for see links
. И последнее, но очень важное: вам надо убедиться, что у вас также установлен
You must be registered for see links
.Как только вы настроили окружение, вы можете скопировать мой код в файл с расширением .py и выполнить следующую команду:
python spritething.py [SPRITE_DIMENSIONS] [NUMBER] [IMAGE_SIZE]
Например, команда для создания первой матрицы спрайтов сверху будет выглядеть так:
python spritething.py 7 30 1900
Общий код.
import PIL, random, sys
from PIL import Image, ImageDraw
origDimension = 1500
r = lambda: random.randint(50,215)
rc = lambda: (r( ), r( ), r( ))
listSym = [ ]
def create_square(border, draw, randColor, element, size):
if (element == int(size/2)):
draw.rectangle(border, randColor)
elif (len(listSym) == element+1):
draw.rectangle(border,listSym.pop())
else:
listSym.append(randColor)
draw.rectangle(border, randColor)
def create_invader(border, draw, size):
x0, y0, x1, y1 = border
squareSize = (x1-x0)/size
randColors = [rc(), rc(), rc(), (0,0,0), (0,0,0), (0,0,0)]
i = 1
for y in range(0, size):
i *= -1
element = 0
for x in range(0, size):
topLeftX = x*squareSize + x0
topLeftY = y*squareSize + y0
botRightX = topLeftX + squareSize
botRightY = topLeftY + squareSize
create_square((topLeftX, topLeftY, botRightX, botRightY), draw, random.choice(randColors), element, size)
if (element == int(size/2) or element == 0):
i *= -1;
element += i
def main(size, invaders, imgSize):
origDimension = imgSize origImage = Image.new('RGB', (origDimension, origDimension))
draw = ImageDraw.Draw(origImage)
invaderSize = origDimension/invaders
padding = invaderSize/size for x in range(0, invaders):
for y in range(0, invaders):
topLeftX = x*invaderSize + padding/2
topLeftY = y*invaderSize + padding/2
botRightX = topLeftX + invaderSize - padding
botRightY = topLeftY + invaderSize - padding
create_invader((topLeftX, topLeftY, botRightX, botRightY), draw, size)
origImage.save("Examples/Example-"+str(size)+"x"+str(size)+"-"+str(invaders)+"-"+str(imgSize)+".jpg")
if __name__ == "__main__":
main(int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]))
Это решение далеко от совершенства, но оно демонстрирует, что создание процедурального искусства не требует тонны кода. Я постараюсь объяснить ключевые моменты.
Функция main() начинается с создания исходного изображения и определения размера спрайтов. Два цикла for отвечают за создание рамок для каждого спрайта, просто разделяя изображение на количество желаемых спрайтов. Эти значения используются для определения координат для каждого из них.
Давайте пропустим padding и взглянем на изображение ниже. Представьте себе, что каждый из четырех квадратов представляет собой спрайт с длиной сторон 1. Граница, которая передается следующей функции, относится к верхним левым и нижним правым координатам. Таким образом, кортеж (координаты) для верхнего левого спрайта будет равен (0,0,1,1), а кортеж для верхнего правого — (1,0,2,1). Они будут использоваться в качестве размеров и базовых координат для квадратов каждого спрайта.
Пример определения рамок спрайта
Функция create_invader() определяет границу для каждого квадрата внутри спрайта. Такой же процесс применяется ниже (см.рисунок), только вместо полного изображения мы используем заранее определенную границу. Эти итоговые координаты для каждого квадрата будут использоваться в следующей функции, чтобы, собственно, нарисовать спрайт.
Пример разбивки спрайта 3х3
Чтобы определить цвет, используется простой массив из трех случайных RGB и трех черных цветов, что дает 50% вероятность получения черного пикселя. За генерирование значений RGB отвечают функции lambda, расположенные в верхней части кода.
Настоящая хитрость этой функции заключается в создании симметрии. Каждый квадрат соединен со значением элемента. На рисунке ниже вы можете видеть, как значения элементов увеличиваются по мере их достижения центра, а затем уменьшаются. Квадраты с соответствующими значениями элементов рисуются одним и тем же цветом.
Значения элементов и симметричные цвета для строки в спрайте 7x7
Ввиду того, что create_square() получает свои занчения от create_invader(), мы используем очередь и значения элементов из before для создания симметрии. При первом появлении значений нового цвета, они попадают в в очередь, а цвет в зеркальных относительно центра квадратах заменяется.
Итоговый процесс генерации спрайтов.
Я понял, как трудно прочесть и понять чье-то решение в коде, и непродуманность кода определенно не помогает в этом, но, надеюсь, у вас теперь есть довольно хорошее представление о том, как это работает. В конце концов, было бы классно, если бы вы смогли полностью отказаться от моего кода и найти совершенно другое решение.
Вывод.
Процедуральное искусство требует время, чтобы отдать ему должное, но это того стоит. Мне нравится сочетать программирование с более традиционным визуальными средствами, и я определенно многому научился в каждом из своих проектов.
В целом, возможно, есть и более полезные проекты, и процедуральное искусство может быть не тем, в чем вы хотите получить опыт, но это очень весело, и вы никогда не знаете точно, как это поможет вам в будущем.
Спасибо за прочтение!
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links



