代码之家  ›  专栏  ›  技术社区  ›  ark.pytm

将操纵杆轴值转换为十六进制三元组代码

  •  1
  • ark.pytm  · 技术社区  · 7 年前

    在pygame中使用PS4控制器,我已经知道如何捕捉轴旋转,轴旋转可以变化为-1或1,但我不知道如何将这些数字转换为 色环 将其转换为十六进制三元组数。
    模拟颜色环的值比任何东西都重要,因为我不希望操纵杆在不运动时捕捉颜色。 Picture
    (因为这有点让人困惑,基本上我希望能够移动我的操纵杆,并根据它移动的位置捕获准确的十六进制三元组编号)

    这是我目前的代码:

    import pygame
    
    # Define some colors
    BLACK    = (   0,   0,   0)
    WHITE    = ( 62, 210, 255)
    
    # This is a simple class that will help us print to the screen
    # It has nothing to do with the joysticks, just outputting the
    # information.
    class TextPrint:
        def __init__(self):
            self.reset()
            self.font = pygame.font.Font(None, 25)
    
        def print(self, screen, textString):
            textBitmap = self.font.render(textString, True, BLACK)
            screen.blit(textBitmap, [self.x, self.y])
            self.y += self.line_height
    
        def reset(self):
            self.x = 25
            self.y = 25
            self.line_height = 30
    
        def indent(self):
            self.x += 10
    
        def unindent(self):
            self.x -= 10
    
    
    pygame.init()
    
    # Set the width and height of the screen [width,height]
    size = [900, 1080]
    screen = pygame.display.set_mode(size)
    
    pygame.display.set_caption("PS4Testing")
    
    #Loop until the user clicks the close button.
    done = False
    
    # Used to manage how fast the screen updates
    clock = pygame.time.Clock()
    
    # Initialize the joysticks
    pygame.joystick.init()
    
    # Get ready to print
    textPrint = TextPrint()
    
    # -------- Main Program Loop -----------
    while done==False:
        # EVENT PROCESSING STEP
        for event in pygame.event.get(): # User did something
            if event.type == pygame.QUIT: # If user clicked close
                done=True # Flag that we are done so we exit this loop
    
    
    
    
        screen.fill(WHITE)
        textPrint.reset()
    
        # Get count of joysticks
        joystick_count = pygame.joystick.get_count()
    
    
        # For each joystick:
        for i in range(joystick_count):
            joystick = pygame.joystick.Joystick(i)
            joystick.init()
    
            # Usually axis run in pairs, up/down for one, and left/right for
            # the other.
            axes = joystick.get_numaxes()
    
    
            for i in range( axes ):
                axis = joystick.get_axis( i )
                textPrint.print(screen, "Axis {} value: {:>6.3f}".format(i, axis) )
            textPrint.unindent()
    
    
    
        # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
    
        # Go ahead and update the screen with what we've drawn.
        pygame.display.flip()
    
        # Limit to 20 frames per second
        clock.tick(20)
    
    # Close the window and quit.
    # If you forget this line, the program will 'hang'
    # on exit if running from IDLE.
    pygame.quit ()
    

    修改代码自 official pygame documentation
    任何帮助都将不胜感激

    1 回复  |  直到 7 年前
        1
  •  1
  •   OSA413    7 年前

    我的计划:

    1. 查找斗杆式操纵手柄的角度
    2. 使用HSV和斗杆角度获取RGB值
    3. 转换为十六进制

    查找操纵手柄斗杆的角度

    首先,我们需要找到操纵杆的角度。我们可以使用 law of cosines 和轴语句作为三角形边的长度(因为它们来自一个点/中心)。

    在此块中存储axis语句:

    for i in range( axes ):
            axis = joystick.get_axis( i )
            #Storing axis statement
            if i == 0:
                Xaxis = axis
            elif i == 1:
                Yaxis = axis
    
            textPrint.print(screen, "Axis {} value: {:>6.3f}".format(i, axis) )
    

    我们存储它们是因为在for循环中,一次只能获取一条语句。

    然后定义一个返回斗杆角度的函数。我们需要使用 math 的模块 pi acos .

    def get_angle(Xaxis,Yaxis):
        #To avoid ZeroDivisionError
        #P.S. - you can improve it a bit.
        if Xaxis == 0:
            Xaxis = 0.001
        if Yaxis == 0:
            Yaxis = 0.001
        #defining the third side of a triangle using the Pythagorean theorem
        b = ((Xaxis)**2 + (Yaxis)**2)**0.5
        c = Xaxis
        a = Yaxis
        #Using law of cosines we'll find angle using arccos of cos
        #math.acos returns angles in radians, so we need to multiply it by 180/math.pi
        angle =  math.acos((b**2 + c**2 - a**2) / (2*b*c)) * 180/math.pi
        #It'll fix angles to be in range of 0 to 360
        if Yaxis > 0:
            angle = 360 - angle
        return angle
    

    现在 get_angle(Xaxis,Yaxis) 将返回斗杆的角度。东为0°,北为90°,西为180°,南为270°。

    获取HSV并转换为RGB

    我们有棍子的角度,我们可以用它来制作HSV颜色,然后将其转换为RGB,因为色轮是基于颜色的色调。

    色调的范围与木棍的角度相同,因此我们可以使用木棍的角度作为色调。

    使用中的公式 Wikipedia ,定义将HSV转换为RGB的函数。

    def hsv_to_rgb(H,S,V):
        #0 <= H <= 360
        #0 <= S <= 1
        #0 <= V <= 1
        C = V * S
        h = H/60
        X = C * (1 - abs(h % 2 -1))
    
        #Yes, Python can compare like "0 <= 2 > 1"
        if 0 <= h <= 1:
            r = C; g = X; b = 0
        elif 1 <= h <= 2:
            r = X; g = C; b = 0
        elif 2 <= h <= 3:
            r = 0; g = C; b = X
        elif 3 <= h <= 4:
            r = 0; g = X; b = C
        elif 4 <= h <= 5:
            r = X; g = 0; b = C
        elif 5 <= h < 6:
            r = C; g = 0; b = X
    
        m = V - C
    
        #Final computing and converting from 0 - 1 to 0 - 255 
        R = int((r+m)*255)
        G = int((g+m)*255)
        B = int((b+m)*255)
    
        return [R,G,B]
    

    现在 hsv_to_rgb(get_angle(Xaxis,Yaxis),1,1) 将返回0-255范围内的红色、绿色和蓝色列表(以便于十六进制转换)。在这种情况下,不需要饱和度和值。

    转换为十六进制

    最简单的部分。我们需要得到RGB列表并将值转换为十六进制。

    colors = hsv_to_rgb(get_angle(Xaxis,Yaxis),1,1)
    #Converting to hex
    lst = list(map(hex,colors))
    #Cutting the "0x" part
    for i in range(len(lst)):
        lst[i] = lst[i][2:]
        #If one of the colors has only one digit, extra 0 will be added for a better look
        if len(lst[i]) == 1:
            lst[i] = "0"+str(lst[i])
    print(get_angle(Xaxis,Yaxis))
    

    类似于 #ff0000 , #00ff00 #0000ff 将打印。

    您还可以使您的程序实时显示颜色变化,只需添加 WHITE = colors 在这个街区。 如果你患有光敏性癫痫,不要使用它。

    合并所有内容

    将两个函数从第一点和第二点放在开头的某个位置。

    将存储从第一个点添加到块

    for i in range( axes ):
        axis = joystick.get_axis( i )
        textPrint.print(screen, "Axis {} value: {:>6.3f}".format(i, axis) )
    

    从块后的第三个点添加转换。我建议创建死亡区功能。

    death_zone = 0.1
    if abs(Xaxis) > death_zone or abs(Yaxis) > death_zone:
        #If you prefer HSV color wheel, use hsv_to_rgb(get_angle(Xaxis,Yaxis),1,1)
        #Else if you prefer RGB color wheel, use hsv_to_rgb(360-get_angle(Xaxis,Yaxis),1,1)
        colors = hsv_to_rgb(get_angle(Xaxis,Yaxis),1,1)
        #Converting to hex
        lst = list(map(hex,colors))
        #Cutting the "0x" part
        for i in range(len(lst)):
            lst[i] = lst[i][2:]
            #If one of the colors has only one digit, extra 0 will be added for a better look
            if len(lst[i]) == 1:
                lst[i] = "0"+str(lst[i])
        print("#"+"".join(lst))
    

    这就是您的代码的外观:

    P、 您可能需要更改一些代码,因为我想我的操纵杆的轴没有被正确捕获。

    import pygame
    import math
    
    # Define some colors
    BLACK    = (   0,   0,   0)
    WHITE    = ( 62, 210, 255)
    
    def hsv_to_rgb(H,S,V):
        #Accirding to https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
        #0 <= H <= 360
        #0 <= S <= 1
        #0 <= V <= 1
        C = V * S
        h = H/60
        X = C * (1 - abs(h % 2 -1))
    
        #Yes, Python can compare like "0 <= 2 > 1"
        if 0 <= h <= 1:
            r = C; g = X; b = 0
        elif 1 <= h <= 2:
            r = X; g = C; b = 0
        elif 2 <= h <= 3:
            r = 0; g = C; b = X
        elif 3 <= h <= 4:
            r = 0; g = X; b = C
        elif 4 <= h <= 5:
            r = X; g = 0; b = C
        elif 5 <= h < 6:
            r = C; g = 0; b = X
    
        m = V - C
    
        #Final computing and converting from 0 - 1 to 0 - 255 
        R = int((r+m)*255)
        G = int((g+m)*255)
        B = int((b+m)*255)
    
        return [R,G,B]
    
    def get_angle(Xaxis,Yaxis):
        #To avoid ZeroDivisionError
        #P.S. - you can improve it a bit.
        if Xaxis == 0:
            Xaxis = 0.001
        if Yaxis == 0:
            Yaxis = 0.001
        #defining the third side of a triangle using the Pythagorean theorem
        b = ((Xaxis)**2 + (Yaxis)**2)**0.5
        c = Xaxis
        a = Yaxis
        #Using law of cosines we'll fing angle using arccos of cos
        #math.acos returns angles in radians, so we need to multiply it by 180/math.pi
        angle =  math.acos((b**2 + c**2 - a**2) / (2*b*c)) * 180/math.pi
        #It'll fix angles to be in range of 0 to 360
        if Yaxis > 0:
            angle = 360 - angle
        return angle
    
    # This is a simple class that will help us print to the screen
    # It has nothing to do with the joysticks, just outputting the
    # information.
    class TextPrint:
        def __init__(self):
            self.reset()
            self.font = pygame.font.Font(None, 25)
    
        def print(self, screen, textString):
            textBitmap = self.font.render(textString, True, BLACK)
            screen.blit(textBitmap, [self.x, self.y])
            self.y += self.line_height
    
        def reset(self):
            self.x = 25
            self.y = 25
            self.line_height = 30
    
        def indent(self):
            self.x += 10
    
        def unindent(self):
            self.x -= 10
    
    
    pygame.init()
    
    # Set the width and height of the screen [width,height]
    size = [900, 1080]
    screen = pygame.display.set_mode(size)
    
    pygame.display.set_caption("PS4Testing")
    
    #Loop until the user clicks the close button.
    done = False
    
    # Used to manage how fast the screen updates
    clock = pygame.time.Clock()
    
    # Initialize the joysticks
    pygame.joystick.init()
    
    # Get ready to print
    textPrint = TextPrint()
    
    # -------- Main Program Loop -----------
    while done==False:
        # EVENT PROCESSING STEP
        for event in pygame.event.get(): # User did something
            if event.type == pygame.QUIT: # If user clicked close
                done=True # Flag that we are done so we exit this loop
    
    
    
    
        screen.fill(WHITE)
        textPrint.reset()
    
        # Get count of joysticks
        joystick_count = pygame.joystick.get_count()
    
    
        # For each joystick:
        for i in range(joystick_count):
            joystick = pygame.joystick.Joystick(i)
            joystick.init()
    
            # Usually axis run in pairs, up/down for one, and left/right for
            # the other.
            axes = joystick.get_numaxes()
    
    
            for i in range( axes ):
                axis = joystick.get_axis( i )
                #Storing axis statement
                if i == 0:
                    Xaxis = axis
                elif i == 1:
                    Yaxis = axis
    
                textPrint.print(screen, "Axis {} value: {:>6.3f}".format(i, axis) )
            textPrint.unindent()
    
            #If joystick is not in the center
            #Death zone is used to not capture joystick if it's very close to the center
            death_zone = 0.1
            if abs(Xaxis) > death_zone or abs(Yaxis) > death_zone:
                #If you prefer HSV color wheel, use hsv_to_rgb(get_angle(Xaxis,Yaxis),1,1)
                #Else if you prefer RGB color wheel, use hsv_to_rgb(360-get_angle(Xaxis,Yaxis),1,1)
                colors = hsv_to_rgb(get_angle(Xaxis,Yaxis),1,1)
                #Converting to hex
                lst = list(map(hex,colors))
                #Cutting the "0x" part
                for i in range(len(lst)):
                    lst[i] = lst[i][2:]
                    #If one of the colors has only one digit, extra 0 will be added for a better look
                    if len(lst[i]) == 1:
                        lst[i] = "0"+str(lst[i])
                print("#"+"".join(lst))
                #You can use it to see color change in real time.
                #But I don't recomend to use it if you have photosensitive epilepsy.
                #WHITE = colors
    
        # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
    
        # Go ahead and update the screen with what we've drawn.
        pygame.display.flip()
    
        # Limit to 20 frames per second
        clock.tick(20)
    
    # Close the window and quit.
    # If you forget this line, the program will 'hang'
    # on exit if running from IDLE.
    pygame.quit ()