代码之家  ›  专栏  ›  技术社区  ›  Jacques Amsel

如何在pygame中从一种颜色淡入另一种颜色?

  •  3
  • Jacques Amsel  · 技术社区  · 6 年前

    def colour():
        switcher = {
            0: 0x2FD596,
            1: 0x2FC3D5,
            2: 0x2F6BD5,
            3: 0x432FD5,
            4: 0x702FD5,
            5: 0xBC2FD5,
            6: 0xD52F91,
            7: 0xD52F43,
            8: 0xD57F2F,
            9: 0xD5D52F,
            10: 0x64D52F,
            11: 0x2FD557,
        }
        return switcher.get(round((datetime.datetime.now() - starting_time).total_seconds()%11))
    

    但在颜色和看起来笨重之间有很大的差距。

    5 回复  |  直到 6 年前
        1
  •  5
  •   sloth    6 年前

    关键是简单地计算每一步你需要改变多少通道(a,r,g和b)。皮加梅的 Color 类非常方便,因为它允许在每个通道上进行迭代,并且它的输入是灵活的,所以您可以只更改例如。 'blue' 0x2FD596 在下面的示例中,它仍将运行。

    下面是一个简单的运行示例:

    import pygame
    import itertools
    
    pygame.init()
    
    screen = pygame.display.set_mode((800, 600))
    
    colors = itertools.cycle(['green', 'blue', 'purple', 'pink', 'red', 'orange'])
    
    clock = pygame.time.Clock()
    
    base_color = next(colors)
    next_color = next(colors)
    current_color = base_color
    
    FPS = 60
    change_every_x_seconds = 3.
    number_of_steps = change_every_x_seconds * FPS
    step = 1
    
    font = pygame.font.SysFont('Arial', 50)
    
    running = True
    while running:
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
    
        text = font.render('fading {a} to {b}'.format(a=base_color, b=next_color), True, pygame.color.Color('black'))
    
        step += 1
        if step < number_of_steps:
            # (y-x)/number_of_steps calculates the amount of change per step required to 
            # fade one channel of the old color to the new color
            # We multiply it with the current step counter
            current_color = [x + (((y-x)/number_of_steps)*step) for x, y in zip(pygame.color.Color(base_color), pygame.color.Color(next_color))]
        else:
            step = 1
            base_color = next_color
            next_color = next(colors)
    
        screen.fill(pygame.color.Color('white'))
        pygame.draw.circle(screen, current_color, screen.get_rect().center, 100)
        screen.blit(text, (230, 100))
        pygame.display.update()
        clock.tick(FPS)
    

    enter image description here


    ...
    change_every_x_milliseconds = 3000.
    step = 0
    
    running = True
    while running:
    
        ...
    
        if step < change_every_x_milliseconds:
            current_color = [x + (((y-x)/change_every_x_milliseconds)*step) for x, y in zip(pygame.color.Color(base_color), pygame.color.Color(next_color))]
        else:
            ...
        ...
    
        pygame.display.update()
        step += clock.tick(60)
    
        2
  •  3
  •   Code Enjoyer    6 年前

    你可以将一种颜色的所有值转换成一个整数,增加数字,然后将其转换回十六进制,从而将所有值从一种颜色转换到另一种颜色。然后循环直到达到下一个值,如下所示:

    value1 = 0xff00ff
    value2 = 0xffffff
    increment = 1 # amount to decrease or increase the hex value by
    while value1 != value2:
        if value1 > value2:
            if int(value1)-increment < int(value2): # failsafe if the increment is greater than 1 and it skips being the value
                value1 = value2
            else:
                value1 = hex(int(value1)-increment)
        else:
            if int(value1)+increment > int(value2):
                value1 = value2
            else:
                value1 = hex(int(value1)+increment)
        code_to_change_colour(value1)
    

    请参阅editbyrune以获得更优雅的实现。请注意 code_to_change_colour(value1) def fade(value1, value2) .


    注意,您所写的大部分内容都是“仅仅”循环控制。您已经知道开始和停止值以及固定的增量。这表明 for 循环而不是 while

    value1 = int(0xff00ff)
    value2 = int(0xffffff)
    increment = 1 if value1 < value2 else -1
    
    for current in range(value1, value2, increment):
        code_to_change_colour(hex(value1))
    
    value1 = value2        
    
        3
  •  2
  •   001    6 年前

    如果只想计算颜色(不使用任何曲面),可以执行以下操作:

    首先,你需要确定你想溶解多久。您还需要存储原始颜色和最终颜色。最后,计算混合物。我将为此创建一个类:

    import pygame
    import time
    
    class color_blend:
        def __init__(self, start_color, end_color, duration=1000):
            self.start_color = pygame.Color(start_color.r, start_color.g, start_color.b)
            self.current_color = pygame.Color(start_color.r, start_color.g, start_color.b)
            self.end_color = end_color
            self.duration = float(duration)
            self.start_time = color_blend.millis()
    
        # Return current time in ms
        @staticmethod
        def millis():
            return (int)(round(time.time() * 1000))
    
        # Blend any 2 colors
        # 0 <= amount <= 1 (0 is all initial_color, 1 is all final_color)
        @staticmethod
        def blend_colors(initial_color, final_color, amount):
            # Calc how much to add or subtract from start color
            r_diff = (final_color.r - initial_color.r) * amount
            g_diff = (final_color.g - initial_color.g) * amount
            b_diff = (final_color.b - initial_color.b) * amount
    
            # Create and return new color
            return pygame.Color((int)(round(initial_color.r + r_diff)),
                                (int)(round(initial_color.g + g_diff)),
                                (int)(round(initial_color.b + b_diff)))
    
        def get_next_color(self):
            # Elapsed time in ms
            elapsed_ms = color_blend.millis() - self.start_time
    
            # Calculate percentage done (0 <= pcnt_done <= 1)
            pcnt_done = min(1.0, elapsed_ms / self.duration)
    
            # Store new color
            self.current_color = color_blend.blend_colors(self.start_color, self.end_color, pcnt_done)
            return self.current_color
    
        def is_finished(self):
            return self.current_color == self.end_color
    
    # Blend red to green in .3 seconds
    c = color_blend(pygame.Color(255, 0, 0), pygame.Color(0, 255, 0), 300)
    while not c.is_finished():
        print(c.get_next_color())
    

    你可以很容易地修改这个做非线性混合。例如,在 blend_colors : amount = math.sin(amount * math.pi)

    (我不是Pygame专家-可能已经有一个内置的函数了。)

        4
  •  1
  •   Prune    6 年前

    set_alpha() 以执行淡入。一旦你完全使用了新的颜色,让它成为前景,然后用你的第三种颜色做一个新的背景。根据需要重复。

    This question 设置阿尔法() 应该能让你完成这项工作。

    够你搬家了吗?

        5
  •  1
  •   skrx    6 年前

    我迟疑不肯发帖,因为我的答案和斯洛的几乎一样,但我只想提一下 linear interpolation (短 lerp ,也称为 mix 在OpenGL/GLSL中)。它通常用于混合两种颜色,但不幸的是pygame Color 类没有lerp方法,因此必须定义自己的方法 勒普 函数并使用列表理解来插值RGBA值。

    勒普 从Wikipedia移植到Python的函数( t 是权重,必须介于0和1之间):

    def lerp(v0, v1, t):
        return (1 - t) * v0 + t * v1
    

    现在,您可以使用列表理解命令两种颜色的RGBA值。

    color = [lerp(v0, v1, t) for v0, v1 in zip(color1, color2)]
    

    >>> [lerp(v0, v1, .5) for v0, v1 in zip((0, 0, 0), (255, 255, 255))]
    [127.5, 127.5, 127.5]
    >>> [lerp(v0, v1, .25) for v0, v1 in zip((0, 0, 0), (255, 255, 255))]
    [63.75, 63.75, 63.75]
    

    如果不需要alpha通道,也可以使用pygame的 Vector3 勒普 方法为你的颜色,那么你只需要写: color = color1.lerp(color2, t) .

    import itertools
    import pygame as pg
    from pygame.math import Vector3
    
    
    pg.init()
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    
    color_cycle = itertools.cycle([
        Vector3(255, 0, 0),
        Vector3(0, 255, 0),
        Vector3(255, 255, 0),
        Vector3(0, 0, 255),
        ])
    
    color1 = next(color_cycle)
    color2 = next(color_cycle)
    color = color1
    start_time = pg.time.get_ticks()
    time_interval = 2000  # milliseconds
    t = 0
    
    done = False
    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
    
        now = pg.time.get_ticks()
        t = (now - start_time) / time_interval
    
        if t > 1:
            t = 0
            start_time = now
            color1, color2 = color2, next(color_cycle)
    
        color = color1.lerp(color2, t)  # Lerp the two colors.
    
        screen.fill(color)
        pg.display.flip()
        clock.tick(60)
    
        6
  •  0
  •   Nicholas Kimble Poling    5 年前

    R=X,G=Y,B=Z

    #Nick Poling
    #Fade Test V2
    
    import random
    #import mpmath
    #import sympy
    import time
    import pygame
    import shelve
    import sys
    from pygame.locals import *
    
    #Always Initialize
    pygame.init()
    
    #sympy contains function line_3d?
    #top level?
    #formated string?
    
    #Change Name Displayed in Corner
    MY_FONT = 'freesansbold.ttf'
    FONTSIZE_1 = 20
    pygame.display.set_caption('Fade Test V2')
    GAME_NAME = pygame.font.Font(MY_FONT, FONTSIZE_1)
    
    #Boards
    GAME_SCREEN_WIDTH = 900
    GAME_SCREEN_HEIGHT = 600
    
    Main_Game_Loop = 1
    
    def get_close_out():
        #Save_Game = get_Save_Game()
        pygame.quit()
        sys.exit()
    
    def get_Save_Game():
        #Save
        global Main_Game_Loop
        global GAME_SCREEN_COLOR
        global GAME_SCREEN_WIDTH
        global GAME_SCREEN_HEIGHT
        saveGameShelfFile = shelve.open('Fade Test V1')
        saveGameShelfFile['GAME_SCREEN_WIDTH'] = GAME_SCREEN_WIDTH
        saveGameShelfFile['GAME_SCREEN_HEIGHT'] = GAME_SCREEN_HEIGHT
    
    def get_Load_Game():
        global Main_Game_Loop
        global GAME_SCREEN_COLOR
        global GAME_SCREEN_WIDTH
        global GAME_SCREEN_HEIGHT
        try:
            #Load
            saveGameShelfFile = shelve.open('Fade Test V1')
            GAME_SCREEN_WIDTH = saveGameShelfFile['GAME_SCREEN_WIDTH']
            GAME_SCREEN_HEIGHT = saveGameShelfFile['GAME_SCREEN_HEIGHT']
        except:
            #Save
            #Save_Game = get_Save_Game()
            #Load
            saveGameShelfFile = shelve.open('Fade Test V1')
            GAME_SCREEN_WIDTH = saveGameShelfFile['GAME_SCREEN_WIDTH']
            GAME_SCREEN_HEIGHT = saveGameShelfFile['GAME_SCREEN_HEIGHT']
        GAME_SCREEN = pygame.display.set_mode((GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT),pygame.RESIZABLE)
        #By putting the GAME_SCREEN here you can make the resize doable with the press of a button
        #Does need to be un "#" to work when press "L"
    
    def get_Colors():
        #Colors
        global BLACK
        global WHITE
        BLACK = [0, 0, 0]
        WHITE = [255,255,255]
    
    def get_Main_Game():
        global Main_Game_Loop
        global GAME_SCREEN_COLOR
        global GAME_SCREEN_WIDTH
        global GAME_SCREEN_HEIGHT
        global BLACK
        global WHITE
        global Point_1
        global Point_2
        global Vector_1
        global Vector_2
        Colors = get_Colors()
        GAME_SCREEN_COLOR = BLACK
        #Load_Game = get_Load_Game()
        GAME_SCREEN = pygame.display.set_mode((GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT),pygame.RESIZABLE)
        while Main_Game_Loop == 1:
            GAME_SCREEN.fill(GAME_SCREEN_COLOR)
            Equation_Of_Lines_in_3D_Space = get_Equation_Of_Lines_in_3D_Space()
            for t in range(0,255):
                XYZ_1 = [Point_1[0] + (Vector_1[0] * t), Point_1[1] + (Vector_1[1] * t), Point_1[2] + (Vector_1[2] * t)]
                XYZ_2 = [Point_2[0] + (Vector_2[0] * t), Point_2[1] + (Vector_2[1] * t), Point_2[2] + (Vector_2[2] * t)]
                GAME_SCREEN_COLOR = XYZ_1
                GAME_SCREEN.fill(GAME_SCREEN_COLOR)
                ticks = pygame.time.delay(5)
                pygame.display.update()
                for event in pygame.event.get():
                    if event.type == QUIT:
                        close_out = get_close_out()
                    elif event.type == pygame.VIDEORESIZE:
                        # There's some code to add back window content here.
                        surface = pygame.display.set_mode((event.w, event.h),pygame.RESIZABLE)
                        GAME_SCREEN_HEIGHT = event.h
                        GAME_SCREEN_WIDTH = event.w
            pygame.display.update()
    
    def get_Equation_Of_Lines_in_3D_Space():
        global Point_1
        global Point_2
        global BLACK
        global WHITE
        global Vector_1
        global Vector_2
        global LCM_X1
        global LCM_X2
        global LCM_Y1
        global LCM_Y2
        global LCM_Z1
        global LCM_Z2
        Point_1 = BLACK
        Point_2 = WHITE
        Vector_1 = []
        Vector_2 = []
        LCM_X1 = []
        LCM_X2 = []
        LCM_Y1 = [] 
        LCM_Y2 = [] 
        LCM_Z1 = []
        LCM_Z2 = []
        for i in range(0,3):
            #
            Delta_XYZ_1 = Point_2[i] - Point_1[i]
            Vector_1.append(Delta_XYZ_1)
            Delta_XYZ_2 = Point_1[i] - Point_2[i]
            Vector_2.append(Delta_XYZ_2)
        factors = get_factors()
    
    def get_factors():
        global num_1
        global num_2
        global Vector_1
        global Vector_2
        global LCM_XYZ_1
        global LCM_XYZ_2
        for i in range(1,7):
            if i == 1:
                num_1 = Vector_1[0]
                num_2 = 1
            elif i == 2:
                num_1 = Vector_2[0]
                num_2 = 2
            elif i == 3:
                num_1 = Vector_1[1]
                num_2 = 3
            elif i == 4:
                num_1 = Vector_2[1]
                num_2 = 4
            elif i == 5:
                num_1 = Vector_1[2]
                num_2 = 5
            elif i == 6:
                num_1 = Vector_2[2]
                num_2 = 6
            get_largest_and_lowest_common_factors(num_1)
        get_LCM_XYZ()
        Vector_1[0] = Vector_1[0] / LCM_XYZ_1[0]
        Vector_1[1] = Vector_1[1] / LCM_XYZ_1[0]
        Vector_1[2] = Vector_1[2] / LCM_XYZ_1[0]
        #
        Vector_2[0] = Vector_2[0] / LCM_XYZ_2[0]
        Vector_2[1] = Vector_2[1] / LCM_XYZ_2[0]
        Vector_2[2] = Vector_2[2] / LCM_XYZ_2[0]
    
    def get_largest_and_lowest_common_factors(x):
        global num_1
        global num_2
        global Vector_1
        global Vector_2
        global LCM_X1
        global LCM_X2
        global LCM_Y1
        global LCM_Y2
        global LCM_Z1
        global LCM_Z2
        #This function takes a number and puts its factor into a list
        for i in range(1, x + 1) or range(-x, x - 1, -1):
            try:
                if x % i == 0:
                    if num_1 == Vector_1[0] and num_2 == 1:
                        LCM_X1.append(i)
                    elif num_1 == Vector_1[1] and num_2 == 3:
                        LCM_Y1.append(i)
                    elif num_1 == Vector_1[2] and num_2 == 5:
                        LCM_Z1.append(i)
                    elif num_1 == Vector_2[0] and num_2 == 2:
                        LCM_X2.append(i)
                    elif num_1 == Vector_2[1] and num_2 == 4:
                        LCM_Y2.append(i)
                    elif num_1 == Vector_2[2] and num_2 == 6:
                        LCM_Z2.append(i)
            except  ZeroDivisionError:
                return 0
    
    def get_LCM_XYZ():
        global LCM_X1
        global LCM_Y1
        global LCM_Z1
        global LCM_X2
        global LCM_Y2
        global LCM_Z2
        global LCM_XYZ_1
        global LCM_XYZ_2
        #If 1 is 0
        check_1 = 0
        check_2 = 0
        check_3 = 0
        for i in range(0,3):
            if i == 0:
                if LCM_X1 == [] and LCM_X2 == []:
                    check_1 = 1
            elif i == 1:
                if LCM_Y1 == [] and LCM_Y2 == []:
                    check_2 = 2
            elif i == 2:
                if LCM_Z1 == [] and LCM_Z2 == []:
                    check_3 = 3
        F_check = check_1 + check_2 + check_3
        if F_check == 1:
            LCM_X1.extend(LCM_Y1)
            LCM_X2.extend(LCM_Y2)
        elif F_check == 2:
            LCM_Y1.extend(LCM_X1)
            LCM_Y2.extend(LCM_X2)
        elif F_check == 3:
            if check_2 == 0:
                LCM_Z1.extend(LCM_Y1)
                LCM_Z2.extend(LCM_Y2)
            elif check_2 != 0:
                LCM_X1.extend(LCM_Z1)
                LCM_X2.extend(LCM_Z2)
                LCM_Y1.extend(LCM_Z1)
                LCM_Y2.extend(LCM_Z2)
        elif F_check == 4:
            LCM_X1.extend(LCM_Y1)
            LCM_X2.extend(LCM_Y2)
            LCM_Z1.extend(LCM_Y1)
            LCM_Z2.extend(LCM_Y2)
        elif F_check == 5:
            LCM_Y1.extend(LCM_X1)
            LCM_Y2.extend(LCM_X2)
            LCM_Z1.extend(LCM_X1)
            LCM_Z2.extend(LCM_X2)
        elif F_check == 6:
            LCM_X1.append(1)
            LCM_X2.append(1)
            LCM_Y1.append(1)
            LCM_Y2.append(1)
            LCM_Z1.append(1)
            LCM_Z2.append(1)
        LCM_X1 = set(LCM_X1)
        LCM_Y1 = set(LCM_Y1)
        LCM_Z1 = set(LCM_Z1)
        LCM_X2 = set(LCM_X2)
        LCM_Y2 = set(LCM_Y2)
        LCM_Z2 = set(LCM_Z2)
        LCM_XYZ_1 = list(set.intersection(LCM_X1,LCM_Y1,LCM_Z1))
        LCM_XYZ_2 = list(set.intersection(LCM_X2,LCM_Y2,LCM_Z2))
        LCM_XYZ_1.sort(reverse = True)
        LCM_XYZ_2.sort(reverse = True)
    
    
    Main_Game = get_Main_Game()