pygame.mask--图形遮罩模块

用于快速实现完美的碰撞检测,Mask 可以精确到 1 个像素级别的判断

import pygame

pygame.init()
screen = pygame.display.set_mode((500, 400))
pygame.display.set_caption("遮罩")

tu = pygame.image.load('圆红.png').convert()
tu.set_colorkey((255,255,255))   
m=pygame.mask.from_surface(tu)  #从指定 Surface 对象中返回一个 Mask
#返回值:<class 'pygame.mask.Mask'> <Mask(116x113)>
#透明的部分设置为0,不透明部分设置为 1
#说明:基于set_colorkey透明的省略参数2

tu1=pygame.image.load('圆蓝.png').convert_alpha()  #基于像素透明
m1=pygame.mask.from_surface(tu1,127)  #从指定 Surface对象中返回一个 Mask
#基于像素透明的可以设置参数2(threshold)
#参数2:检查每个像素的 alpha 值是否大于参数2指定的值。(alpha 通道使用 0 ~ 255 描述像素的透明度)【默认127】
#【alpha通道小于参数2的为透明,大于参数2的为不透明】

tu2=pygame.image.load('圆红.png').convert_alpha()

x=m.get_size()   #返回Mask 的大小。
# (116, 113)-> (width,height)

x=m.get_at((50,50))  #返回遮罩中指点坐标的值
#参数:坐标
#返回值:0表示透明,1表示不透明

m2=m
m2.set_at((50,50),0)  #给指定坐标设置值
#参数1:坐标
#参数2:值

print(type(x),x)
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
    screen.blit(tu, (0, 0))
    screen.blit(tu1, (300, 0))
    pygame.display.update()

 


import pygame
pygame.init()
red = (255,0,0)
blue = (0,0,255)
w,h = size = 480,360
screen = pygame.display.set_mode(size)
pygame.display.set_caption("遮罩")
clock = pygame.time.Clock()
i=0

# 创建大的圆环
radius1 = 50
width1,height1 = 2*radius1,2*radius1
hollow_circle = pygame.Surface((width1,height1),pygame.SRCALPHA)
pos = width1//2,height1//2
rect1 = hollow_circle.get_rect(center=(w//2,h//2))
pygame.draw.circle(hollow_circle,red,pos,radius1,10)
mask1 = pygame.mask.from_surface(hollow_circle) #获取圆环的Mask
# 创建小的实心圆
radius2 = 10
width2,height2 = 2 * radius2,2 * radius2
solid_circle = pygame.Surface((width2,height2),pygame.SRCALPHA)
pos = width2//2,height2//2
rect2 = solid_circle.get_rect(center=(w//2,h//2))
pygame.draw.circle(solid_circle,blue,pos,radius2)
mask2 = pygame.mask.from_surface(solid_circle)


while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
screen.fill((255,255,255))

mpos = pygame.mouse.get_pos()
rect2.center = mpos

offset = rect2.x - rect1.x, rect2.y - rect1.y
p = mask1.overlap(mask2, offset) #检测两个Mask有没有碰撞
#这种检测法图像的透明区域不在碰撞检测范围内
#没有碰撞返回None,有碰撞返回碰撞的坐标(相对于mask1的坐标)
#返回值:【mask1中碰撞区域左上角的坐标,而且这个坐标是相对于mask1图像左上角的】
screen.blit(hollow_circle, rect1)
screen.blit(solid_circle, rect2)
print(i,p)
i+=1
clock.tick(2)
pygame.display.update()
 

 

import pygame
pygame.init()
red = (255,0,0)
blue = (0,0,255)
screen = pygame.display.set_mode((480,360))
pygame.display.set_caption("mask")
clock = pygame.time.Clock()
i=0

小红块 = pygame.image.load("小红块.png").convert_alpha()
小红块rect = 小红块.get_rect()
测试图 = pygame.image.load("测试图.png").convert_alpha()
测试图.set_colorkey((0,0,0))
#设置透明色,透明区域不在mask碰撞检测范围内
测试图rect = 测试图.get_rect()

测试图rect.x=100
测试图rect.y=100
小红块mask = pygame.mask.from_surface(小红块,127)
测试图mask = pygame.mask.from_surface(测试图,127)
#透明区域的mask值为0


while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                小红块rect.x = 小红块rect.x + 10
            if event.key == pygame.K_LEFT:
                小红块rect.x = 小红块rect.x - 10
            if event.key == pygame.K_UP:
                小红块rect.top = 小红块rect.top - 10
            if event.key == pygame.K_DOWN:
                小红块rect.move_ip(0, 10)
    screen.fill((255,255,255))
    offsetX = 小红块rect.x - 测试图rect.x
    offsetY = 小红块rect.y - 测试图rect.y

    point = 测试图mask.overlap(小红块mask, (offsetX, offsetY))
    someArea = 测试图mask.overlap_area(小红块mask, (offsetX, offsetY))  #返回两个 Mask 重叠的像素数量

    if point:
        px, py = point
        # 借助返回的点,获取返回点的颜色
        pixel1 = 测试图.get_at((px,py))

        sx=测试图rect.x+px
        sy = 测试图rect.y + py
        #相对于screen的坐标

        cx=sx-小红块rect.x
        cy = sy - 小红块rect.y

        pixel2 = 小红块.get_at((cx, cy))
        

    else:
        pixel1=1000
        pixel2=2000

    print(i,point,someArea,pixel1,pixel2)
    screen.blit(测试图,测试图rect )
    screen.blit(小红块, 小红块rect)

    i+=1
    clock.tick(2)
    pygame.display.update()

测试图:

 

 小红块:

 

mask1.fill()  #将所有的位设置为 1
mask1.clear()  #将所有的位设置为0
mask1.invert()  #翻转 Mask 中所有的位(0 变 1,1 变 0)
mask2=mask1.scale((50,50))   #缩放 Mask 的尺寸
#Mask 根据指定尺寸缩放后返回一个新的 Mask

 

import pygame
pygame.init()

w,h = size = 480,360
screen = pygame.display.set_mode(size)
pygame.display.set_caption("遮罩")
clock = pygame.time.Clock()

tu1 = pygame.Surface((6,6),pygame.SRCALPHA)
mask1 = pygame.mask.from_surface(tu1)
#创建一个全部为0的mask

tu2=pygame.Surface((3,3),pygame.SRCALPHA)
pygame.draw.rect(tu2, (0,0,255), (0,0,3,3))
mask2 = pygame.mask.from_surface(tu2)

L1=[]
for i in range(6):
    for j in range(6):
        p = mask1.get_at((i, j))
        L1.append(p)
L2=[]
for i in range(3):
    for j in range(3):
        p = mask2.get_at((i, j))
        L2.append(p)
mask1.draw(mask2, (2,1))   #将mask2绘制到mask1上边,执行的是按位 or 操作
#参数2-偏移量:2表示mask2对应于mask1的位置往下走2行(mask1的第3行与mask2的首行对齐)
#             1表示mask2对应于mask1的位置往右走2列(mask1的第2列与mask2的首列对齐)
#偏移量的意思:【(mask2的行偏移量,列偏移量)】

L3=[]
for i in range(6):
    for j in range(6):
        p = mask1.get_at((i, j))
        L3.append(p)
print('L1')
print(L1)
print('L2')
print(L2)
print('L3')
print(L3)


while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
    screen.fill((255,255,255))

    clock.tick(2)
    pygame.display.update()

意思理解图:

 

n=mask1.count()  #返回 Mask 被设置(为 1)的像素的数量
p=mask1.centroid()  #找到 Mask 的重心点。如果 Mask 是空的,那么返回值是 (0, 0)
#找到mask中所有设置为1的中心点,如果mask所有值都是0,那就返回(0,0)
import pygame
pygame.init()

w,h = size = 200,100
screen = pygame.display.set_mode(size)
pygame.display.set_caption("遮罩")
clock = pygame.time.Clock()

tu1 = pygame.Surface((8,8),pygame.SRCALPHA)
pygame.draw.rect(tu1, (0,0,255), (1,1,4,4))
mask1 = pygame.mask.from_surface(tu1)

f=mask1.outline()  #用列表的形式返回组成对象轮廓的点
#[(1, 1), (2, 1), (3, 1), (4, 1), (4, 2), (4, 3), (4, 4), (3, 4), (2, 4), (1, 4), (1, 3), (1, 2), (1, 1)]

print(f)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
    screen.fill((255,255,255))

    clock.tick(2)
    pygame.display.update()

理解图:

 

import pygame
pygame.init()

w,h = size = 400,400
screen = pygame.display.set_mode(size)
pygame.display.set_caption("遮罩")
clock = pygame.time.Clock()

tu1 = pygame.Surface((200,200),pygame.SRCALPHA)
pygame.draw.circle(tu1, (0,0,255), (4,4),3,1)
pygame.draw.ellipse(tu1, (0,0,255), (20,20,20,10),1)
mask1 = pygame.mask.from_surface(tu1)

f=mask1.get_bounding_rects()  #返回具有连续1区域矩形列表
#每个1连续区域形成就形成一个矩形
#返回值:列表
#[<rect(1, 1, 7, 6)>, <rect(20, 20, 20, 10)>]


print(f)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
    screen.fill((255,255,255))

    clock.tick(2)
    pygame.display.update()

 

  

 

 

posted @ 2020-07-09 12:42  天子骄龙  阅读(1636)  评论(0编辑  收藏  举报