【问题标题】:PyGame: translucent sprites with per pixel alphaPyGame:具有每像素 alpha 的半透明精灵
【发布时间】:2010-11-25 12:05:13
【问题描述】:

是否可以显示具有可控 alpha 的 PyGame 表面?我想采用具有自己的每像素 alpha 的表面并以可变的半透明度显示它而不影响表面数据并保持透明度不变,即表面上的对象将保持其形状但它们的“内容”或多或少半透明。

换句话说,我想将源图像中的每像素 alpha 与运行时计算的每表面 alpha 结合起来。

【问题讨论】:

    标签: python pygame transparent


    【解决方案1】:

    Pygame documentation 表示您不能将表面 alpha 与每像素 alpha 结合起来,但如果您使用的是 Pygame 1.8.1 或更高版本,您可以通过使用 special_flags 参数来解决此问题 @987654324 @。

    我是这样做的:

    # Load an image with per-pixel alpha
    s = pygame.image.load('spam.png')
    s = s.convert_alpha()
    
    # Simulate s.set_alpha(alpha)
    alpha_img = pygame.Surface(s.get_rect().size, pygame.SRCALPHA)
    alpha_img.fill((255, 255, 255, alpha))
    s.blit(alpha_img, (0, 0), special_flags=pygame.BLEND_RGBA_MULT)
    

    其工作方式是创建与第一个相同大小的第二个表面,并使用RGBA multiplication 将其粘贴到第一个表面。通过使第二张图像的 R、G 和 B 分量等于 255,乘法不会影响图像的颜色,但会按给定的 Alpha 因子缩放 Alpha 通道。

    请注意,上述方法与调用set_alpha() 的不同之处在于,set_alpha() 可以通过调用set_alpha(255) 来反转。如果使用上面的方法,会导致每个像素的像素 alpha 值发生变化,所以这个过程不能直接颠倒。

    【讨论】:

    • self 应该是s
    【解决方案2】:

    是的,你可以。 documentation of the Surface class 解释了如何做到这一点。它只归结为两种情况: 在 Surface 对象的创建过程中设置一个标志:

    s = pygame.Surface((16, 16), flags=pygame.SRCALPHA)
    

    或者你给一个还没有 alpha 通道的表面:

    s = pygame.image.load('spam.png')
    s.convert_alpha()
    

    pygame.image 模块的文档说,对于具有透明度的 PNG,应用 convert_alpha 是必要的。

    如果您愿意,您可以使用模块 draw 和 surfarray 修改每个像素的 alpha 值。指定颜色时,使用四个整数的元组:(红色,绿色,蓝色,alpha)。 alpha 参数范围从 0(完全透明)到 255(完全不透明)。

    import pygame
    pygame.init()
    screen = pygame.display.set_mode((320, 200))
    screen.fill((200, 100, 200))
    s = pygame.Surface((64, 64), flags=pygame.SRCALPHA)
    for i in range(64):
        pygame.draw.line(s, (0, 0, 0, i*4), (0, i), (64, i))
    
    screen.blit(s, (50, 30))
    pygame.display.flip()
    

    【讨论】:

    • +1 示例总是受欢迎的。特别是当它工作时,并显示需要什么:D
    • 嗯,这解释了如何显示具有每像素 alpha 的表面(例如,来自 PNG 文件)。我已经意识到这一点。但我正在寻找一种以代码可控的半透明显示这些表面的方法。例如使这些精灵从完全透明变为原始的每像素透明度。类似于 Surface.set_alpha() 但没有禁用表面中已经存在的每像素透明度。将每像素透明度与整体透明度值混合。
    【解决方案3】:

    在检查了 PyGame 和 SDL 文档后,我得出结论,我提出的问题在 PyGame 中使用标准函数是不可行的。

    SDL 文档指出,每像素 alpha 和每表面 alpha 不能与前者结合使用,前者总是优先。实现我想要的效果的唯一方法是编写代码,在 blit 之前更新源表面的每像素 alpha 值。

    【讨论】:

      【解决方案4】:

      如果您的输入图像启用了每像素 alpha,但仅使用一位来实现透明度(例如,具有透明背景或文本的 .png 精灵),您可以将透明背景转换为 colorkey-alpha 背景很容易,然后使用 set_alpha() 将整个纹理混合到任何东西上。

      这是我用来淡化文本效果和其他东西的快速而肮脏的辅助函数:

      def convert_to_colorkey_alpha(surf, colorkey=pygame.color.Color("magenta")):
          newsurf = surface.Surface(surf.get_size())
          newsurf.fill(colorkey)
          newsurf.blit(surf, (0, 0))
          newsurf.set_colorkey(colorkey)
          return newsurf
      

      其他几个可能解决此问题的技巧可能是:

      • 在 blitting 之前进行逐像素编辑以修改 Alpha 通道
      • 使用 special_flags=BLEND_RGBA_MULT 或 BLEND_RGBA_SUB 将白色或黑色填充的半透明表面粘贴到源表面上。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-17
        • 1970-01-01
        • 1970-01-01
        • 2014-01-13
        • 1970-01-01
        相关资源
        最近更新 更多