Pygame - 有没有办法只在面具中进行blit或更新

时间:2013-06-02 05:45:17

标签: python pygame bit-masks

在pygame中是否有任何方法可以在屏幕内的屏幕上显示某些内容。例如:如果你有一个掩码,其中所有位都设置为1,除了topleft corner和全黑图像,而不更改图像,你能保持左上角(与掩码相同)清除吗?只更新掩码(而不是矩形)会有所帮助。

2 个答案:

答案 0 :(得分:7)

好的,如果我正确理解你的问题,那就是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并将其用作你的面具。

编辑:以下是通过编辑曲面生成蒙版的示例:

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"))

它产生了这个结果:

checkerboard mask result

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

答案 1 :(得分:2)

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

pygame.surfarray.blit_array(Destination_surface, my_array)

然后你可以随心所欲地制作任何你想要的数据,但这是另一个故事。