7

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

4

2 回答 2

10

好的,如果我正确理解了您的问题,那么诀窍就是BLEND_RGBA_MULT标志。

我决定自己测试一下,因为我很好奇。我从这张图片开始:

320x240 叶子

我在想要显示图像的地方用白色制作了一张图像,在想要遮罩的地方用透明度制作了图像。我什至给了它不同程度的透明度,看看我是否可以得到模糊遮罩。

模糊圆形面具

^^^ 您可能看不到图像,因为它是透明的白色,但它就在那里。您只需右键单击并下载它。

我加载了两个图像,确保使用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))

果然,它奏效了:

结果

这是我使用的完整代码。

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

它产生这个结果:

棋盘掩码结果

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

于 2013-06-05T01:37:52.907 回答
3

因此,如果我理解正确,那么问题是 - 是否可以使用位掩码进行 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。缓冲区翻转也是如此 - 您可以仅使用矩形列表来描述要更新的屏幕缓冲区区域。更灵活和直接的方法是使用位掩码,但是这也是不可能的。可能将位掩码转换为矩形列表是一种方法,但我没有尝试过。第三种选择是不使用 pygame 的表面并使用 Numpy 作为您的数据,然后使用数组 blitting:缓冲区翻转也是如此 - 您可以仅使用矩形列表来描述要更新的屏幕缓冲区区域。更灵活和直接的方法是使用位掩码,但是这也是不可能的。可能将位掩码转换为矩形列表是一种方法,但我没有尝试过。第三种选择是不使用 pygame 的表面并使用 Numpy 作为您的数据,然后使用数组 blitting:缓冲区翻转也是如此 - 您可以仅使用矩形列表来描述要更新的屏幕缓冲区区域。更灵活和直接的方法是使用位掩码,但是这也是不可能的。可能将位掩码转换为矩形列表是一种方法,但我没有尝试过。第三种选择是不使用 pygame 的表面并使用 Numpy 作为您的数据,然后使用数组 blitting:

pygame.surfarray.blit_array(Destination_surface, my_array)

然后你可以自由地用你的数据做任何你想做的事情,但那是另一回事了。

于 2014-10-18T20:21:26.077 回答