用於快速實現完美的碰撞檢測,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()