Более сложные цветовые градиенты в Pygame - PullRequest
3 голосов
/ 27 апреля 2020

В Python 3.8 с модулем Pygame:

Я пытаюсь сделать цветовые градиенты для цветовой игры, которую я создаю. Я знаю, как сделать одномерный градиент, как это:

enter image description here

Но я хочу иметь возможность создавать изображение с более чем двумя цветами в пределах градиента. Вот пример из целого числа rnet: (игнорируйте причудливый текст)

enter image description here

Как я могу создать функцию для генерации градиента, кратного цвета на поверхности? Важно, чтобы я мог выбирать цвета в углах или, по крайней мере, иметь возможность влиять на них так, чтобы я мог понять.

Идея, которую я нашел в Интернете, такова:

for i in range(900):
   for j in range(900):
      surface.set_at((i,j),(i/4,j/4,i/4))

Моя проблема в том, что трудно выбрать цвета, которые он генерирует. Я не могу собрать воедино, как заставить цвета смешиваться друг с другом, особенно с несколькими из них.

Ответы [ 2 ]

2 голосов
/ 27 апреля 2020

Маги c не задействованы. В Pygame нет API для градиентов, и, хотя вы не опубликовали свой код, вы, вероятно, выполнили интерполяцию очень хорошо.

Итак, для «2-мерного квадратного градиента» вы должны продолжать разбить вашу проблему на более мелкие части, пока вы не получите то, что вы хотите - для этого это может быть: иметь градиент, который проходит в верхней части интересующей вас области при y == 0, другой градиент, который проходит в нижней части вашей области, в y = высота, и для каждого столбца вы интерполируете новый градиент, начиная с цвета на верхнем градиенте и заканчивая цветом на нижнем градиенте.

Единственная плохая новость заключается в том, что это будет очень медленно в Pygame - но вы можете нарисовать его один раз, сохранить полученное изображение и просто загрузить его во время игры.

Существуют другие библиотеки и фреймворки, подходящие для рисования линейного градиента, и сделать это быстрый, как Каир, Гегл и сам OpenGL - но ни у одного из них нет готового способа перевести один полный градиент в другой.

[продолжение ...]

1 голос
/ 28 апреля 2020

Итак, для «двухмерного квадратного градиента» вы должны продолжать разбивать свою проблему на более мелкие части, пока не получите желаемое - для этого это может быть: иметь градиент, который работает на в верхней части интересующей вас области при y = 0, еще один градиент, который проходит в нижней части вашей области, при y = высоте, и для каждого столбца вы интерполируете новый градиент, начиная с цвета на верхнем градиенте и заканчивая цветом в нижнем градиенте.

Это отлично работает! Мне удалось придумать три функции, которые вместе создают великолепные 4-цветовые прямоугольные градиенты angular, каждый из которых находится в отдельном углу. Вот мой код, если вы хотите его использовать:

windowSurface = pygame.display.set_mode((1500,900))
s = pygame.Surface(size, pygame.SRCALPHA)
gradientStorage = pygame.Surface((1500,1500))
colorGridStorage = pygame. Surface((1500,1500))


def colorMix(color1, color2, paletteSize):    # creates a list of colors that gradually fade from color1 to color2, inclusive. paletteSize is the amount of values that will be generated.
               # The smallest useful paletteSize is 3, as it will return [color1, color1MixedWithColor2, color2]
        palette = [color1]
        colorDifference = [ color1[0] - color2[0], color1[1] - color2[1], color1[2] - color2[2] ]

        Rstep = (color1[0] - color2[0]) / (paletteSize -1)
        Gstep = (color1[1] - color2[1]) / (paletteSize -1)
        Bstep = (color1[2] - color2[2]) / (paletteSize -1)

        for i in range(1,paletteSize):
            palette.append((color1[0] - Rstep*i, color1[1] - Gstep*i, color1[2] - Bstep*i))

        palette.append(color2)

        return palette

def createColorGrid(resolution, color1, color2, color3, color4):        # build a new colorGrid using a different process than above. colors are RGB format. For a 1D color fade set pairs of colors
                                      # like (255,0,0) (255,0,0) (0,255,255) (0,255,255). Colors are ordered from top left corner and follow corners clockwise.
        colorArray = [resolution]   # the first value in colorGrid is always a tuple stating the resolution.
        leftColumn = colorMix(color1,color4,resolution[1])
        rightColumn = colorMix(color2,color3,resolution[1])

        for i in range(0,resolution[1]):                                                                  # color processing goes from top left to top right, then down a row and repeat
                colorArray.append(colorMix(leftColumn[i],rightColumn[i],resolution[0]))
        return colorArray


def drawColorGrid(colorGrid, rect):    # input a colorGrid array. This will draw the set of color tiles decided by the colorGrid you pass into it
    colorGridStorage.fill((255,255,255))
    iCounter = 0
    for i in colorGrid:

        jCounter = 0
        if isinstance(i[0], int):   # the first value in colorGrid is the [x,y] resolution. we need to ignore it and move on to the rest
            continue

        for j in i:
            rectX = (rect[0] + round( jCounter * (rect[2]/colorGrid[0][0])))
            rectY = rect[1] + round(iCounter * rect[3]/colorGrid[0][1])
            rectWidth = round(rect[2]/colorGrid[0][0])
            rectHeight = round(rect[3]/colorGrid[0][1])
            pygame.draw.rect(colorGridStorage, j, (rectX,  rectY, rectWidth, rectHeight))
            jCounter += 1
        iCounter +=1
    windowSurface.blit(colorGridStorage, (rect[0], rect[1]))

Чтобы нарисовать новый градиент, сначала используйте createColorGrid (разрешение, color1, color2, color3, color4), чтобы построить массив блоков цветов в определенное разрешение. Низкие разрешения будут выглядеть так же, как в игре I Love Hue. Когда у вас есть переменная colorGrid, вставьте ее в drawColorGrid (colorGrid, rect). Это возьмет массив colorGrid и перетянет его на экран в пределах данного прямоугольника. Поверхность экрана в этом случае называется windowSurface.

Я довольно новый программист, поэтому в приведенном выше коде определенно могут быть некоторые оптимизации. Укажите их мне, если хотите, но этот код отлично работает для приложений, которые я делаю. Кажется, он достаточно плавный, чтобы генерировать и отбрасывать не менее 20 случайных градиентов на полный экран в секунду, что гораздо больше, чем мне нужно.

...