重叠的半透明形状
如果我在一个表面上画任何形状(开启了SRCALPHA标志),并且使用的是部分透明的颜色,那么这个形状会完全覆盖在下面的内容上,而不是像你在图像编辑软件中那样重叠显示。
我该如何让这些形状正确地重叠呢?
3 个回答
Alpha本身只是一个额外的“值”,可以用来达到某种目的。通常情况下,这个目的就是让东西变得透明(当然,它还有其他用途,比如反射、镜面高光,甚至可以用来模拟HDR效果)。
你需要明确告诉程序你想要它进行混合(以及它应该使用什么样的公式来进行混合)。简单在网上搜索一下 “pygame混合模式”,就能找到一些不错的资源。
正如Alex所提到的,blit函数需要一个混合模式作为参数。这个 StackOverflow的问题提供了更多的信息。
你可以使用 blit 方法,并且选择合适的 BLEND_*
值(保持这些形状作为独立的表面,这样方便修改和保持完整性,只有在显示的时候才进行合成)。
正如所提到的,PyGame中的绘图函数并不会像你想的那样进行颜色混合。根据PyGame的文档:
大多数参数都接受一个颜色参数,这个参数是一个RGB三元组。它们也可以接受一个RGBA四元组。如果这个表面包含像素透明度,alpha值会直接写入表面,但绘图函数不会透明绘制。
你可能想要做的,基本上就是Alex Martelli所说的——创建一个带有透明通道的中间软件表面,把你的形状绘制到那个表面上,然后再将其混合到最终的表面上。如果你使用过PyGame的字体渲染,你会发现它的工作方式大致相同,只是Font.render会为你创建临时表面。
我最近对Python和PyGame有点生疏,但这里有一个快速的例子,希望不会有太多错误:
# returns a surface with the circle drawn onto it
def render_transparent_circle(color, radius, width=0):
size = radius * 2
temp_surf = pygame.Surface((size, size), SRCALPHA)
temp_surf.fill(Color(0, 0, 0, 0))
pygame.draw.circle(temp_surf, color, (radius, radius), radius, width)
return temp_surf
# draw a half-opaque blue circle of radius 30 to the display at point (50, 100)
def test():
transp_blue = Color(0, 0, 255, 128)
screen = pygame.display.get_surface()
circle = render_transparent_circle(transp_blue, 30)
screen.blit(circle, (50, 100))
附言——如果你要多次显示同一个形状,可能需要考虑缓存这个中间表面(但别忘了测试一下这样做是否真的有帮助)。