PyGame:具有每像素 alpha 的半透明精灵

Posted

技术标签:

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

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

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

【问题讨论】:

【参考方案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 将白色或黑色填充的半透明表面粘贴到源表面上。

【讨论】:

以上是关于PyGame:具有每像素 alpha 的半透明精灵的主要内容,如果未能解决你的问题,请参考以下文章

图像格式中的Alpha通道是指啥?

iPhone目标C中错误的半透明视图

Pygame 使用精灵表:alpha 问题

如何在pygame中制作具有透明背景的表面

有没有办法让半透明的圆圈背景完全透明,中间是完全不透明的盒子?

为啥 javafx 会破坏我的半透明游标?