Pygame - 有没有仅在掩码中进行blit或update的方法?

7

在pygame中,有没有一种方法可以在掩码内将某些内容绘制到屏幕上。例如:如果您有一个掩码,其中所有位都设置为1,除了左上角和完全黑色的图像,而不改变图像,您能保持左上角(与掩码相同)的清晰吗?只更新掩码(而不是矩形)也会有所帮助。


查看每像素的 alpha 值:http://www.pygame.org/docs/ref/surface.html 我自己对此一无所知,但文档似乎建议这样做。 - ahuff44
你是在询问带有透明度的精灵,还是每个像素具有可变的alpha值,或者只更新屏幕上发生变化的一小部分? - ninMonkey
使用掩码更新显示内容,而不是矩形。 - user1912132
2个回答

12

好的,如果我正确理解您的问题,诀窍在于BLEND_RGBA_MULT标志。

我很好奇,所以决定亲自测试一下。 我从这张图片开始:

320x240 leaves

我制作了一张图像,在我想要显示图像的地方用白色,我想要遮罩的地方用透明度。 我甚至给它不同级别的透明度,看看能否得到模糊的遮罩效果。

Fuzzy circular mask

^^^由于是白色透明背景,因此很难看到该图像。 您只需右键单击并下载即可。

我加载了这两个图像,确保使用了convert_alpha()

background = pygame.image.load("leaves.png").convert_alpha()
mask = pygame.image.load("mask-fuzzy.png").convert_alpha()

然后为了对图像进行遮罩,我复制了要被遮罩的图像。

masked = background.copy()

我使用BLEND_RGBA_MULT将掩码复制到此副本上。

masked.blit(mask, (0, 0), None, pygame.BLEND_RGBA_MULT)

...然后我把它绘制到屏幕上。

display.blit(masked, (0, 0))

果然,它奏效了:

result

这是我使用的完整代码。

import pygame
from pygame.locals import *

pygame.init()
display = pygame.display.set_mode((320, 240))

background = pygame.image.load("leaves.png").convert_alpha()
mask = pygame.image.load("mask-fuzzy.png").convert_alpha()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    # draw
    display.fill(Color(255, 0, 255))
    masked = background.copy()
    masked.blit(mask, (0, 0), None, pygame.BLEND_RGBA_MULT)
    display.blit(masked, (0, 0))
    pygame.display.flip()

如果您想要一个可变的掩码,您可以尝试手动编辑一个 Surface 并将其用作掩码。

编辑:这是一个通过编辑 Surface 生成掩码的示例:

mask = pygame.Surface((320, 240), pygame.SRCALPHA)
for y in range(0, 240):
    for x in range(0, 320):
        if (x/16 + y/16) % 2 == 0:
            mask.set_at((x, y), Color("white"))

它产生了这个结果:

棋盘格掩码结果

现在我想在游戏中使用它!


3
所以,如果我理解正确,问题是-能否使用位掩码进行blitting。答案是肯定的和否定的。据我所知,在pygame中没有对1位掩码的支持,这意味着您必须使用32bpp RGBA(SRCALPHA标志)作为源表面来与透明度混合,而在这种情况下,您使用8位掩码=每像素256级透明度,并且这在先前的回答中有所描述。另一个选项是使用“colorkey” blitting。在这种情况下,它更类似于1比特掩码,并且与标准的24bpp RGB表面一起使用。您只需设置在源表面中不希望写入目标的颜色。请参阅文档中的“Surface.set_colorkey”。但是,使用colorkey方法的问题是,您可能会意外地在源中具有与colorkey相同颜色的某些像素,但仍希望绘制它们。所以你必须小心。我个人使用RGBA表面进行屏蔽,它更强大,但几乎总是不需要8位,1位掩码就足够了。所以对我来说,没有支持每个位掩码blitting似乎有点奇怪。缓冲区翻转也是如此-您只能使用矩形列表描述要更新的屏幕缓冲区的区域。使用位掩码会更加灵活和直接,但据我所知这也是不可能的。可能将位掩码转换为矩形列表是一种方法,但我没有尝试过。第三个选项是不使用pygame表面,而是使用Numpy进行数据处理,然后使用数组blitting:
pygame.surfarray.blit_array(Destination_surface, my_array)

然后您可以自由地使用您的数据制作任何您想要的东西,但这是另一回事。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接