pygame遮罩mask的本质_取自李兴球著《Python创意编程之Pygame教程》(编写中2019/7/18)

为了表示一张图片透明度分布情况,每个像素都多加了一个alpha值。所以我们常常看到用4元组表示的像素值。 即,在一个每像素透明度的surface中。像素值表示为(r,g,b,a)。如果a 的值为0,那么这个像素点渲染到其它surface上时将不会渲染。如果值为255,那么这个像素点将完全渲染到另一个surface上。如果介于0到255之间,则按比例进行渲染,从而我们就能看到半透明效果。

在Pygame模块中有遮罩这个概念,它的英文为mask,也可以叫做掩膜。它的设计目的是用来进行像素级别的碰撞检测的。我们把能接受“碰撞”的地方的mask的位设置为True,即1,把不能授受“碰撞”的mask的位设置为0。那么哪些地方能接受碰撞? 我们规定,透明的地方不接受碰撞,不透明的地方才接受碰撞。所以通过分析alpha值就能设置一张图片每个像素的mask值了。如果一张图片不是每像素模式,那么它可能设置了colorkey颜色。如果这个颜色和colorkey颜色相同,那么就把mask位设置为0,否则为1。为了获取每个位置的mask值,Pygame提供了get_at命令来得到位值或set_at命令来设置位值。它们的使用方法和surface几乎一样,在此不再赘述。我们可以把mask想像成蒙在图像上的薄膜,当然,透明的地方是不会蒙的。surface有宽高,所以mask也有宽高。

默认情况下,所谓的透明的地方指的是alpha值小于等于127。不透明的地方指的是alpha值大于127。这个127是一个阈值。在Pygame中有pygame.mask.from_surface命令。它能从一个surface创建一个mask。这个命令有两个参数,第一个就是surface,第二个是threshold,即阈值。如果一个surface所有像素的alpha值都是60,表示了这张图是一张比较透明的图。但由于在使用pygame.mask.frame_surface命令创建mask时把threshold设为了50,所以它的每一个mask位仍会被设置为1。这个“门槛”可真有点低啊。下面我们编个程序,实践一下。

"""
   mask阈值设定示例程序
   从surface创建mask的时候能设置阈值,小于等于阈值的像素的mask位将被设定为0, 表示不接受碰撞检测。
"""
import pygame

pygame.init()
screen = pygame.display.set_mode((480,360))

width,height = 50,50
x1,y1 = 100,100
sur1 = pygame.Surface((width,height)).convert_alpha()
sur1.fill((255,100,100,60))                 # 60是透明度
sur1_rect = sur1.get_rect(topleft=(x1,y1))  # 获取矩形并定位

# 以下创建mask,设定阈值为50,即小于等于50的mask位都会被设置为0
sur1_mask = pygame.mask.from_surface(sur1,50)  # 取掩膜
print(sur1_mask.get_at((1,1)))              # 取(1,1)掩膜值
screen.blit(sur1,sur1_rect)                 # 贴到屏幕
pygame.display.update()                     # 刷新屏幕显示

You must log in to read the rest of this article. Please log in or register as a user.