蒙版
蒙版是二值化的图像,每个像素的值只能是0或1。
mask(蒙版)的用途:
- 碰撞检测
- 部分着色
案例
和字母的碰撞检测
.
当玩家碰到字母α \alphaα时,改变玩家颜色为绿色,否则为红色。
注意:我们希望碰到字母α \alphaα时才变色,而不是碰到字母α \alphaα所在的矩形就变色。
# collision if pygame.sprite.spritecollide(player.sprite,obstacle,False): if pygame.sprite.spritecollide(player.sprite,obstacle,False,pygame.sprite.collide_mask): player.sprite.image.fill('green') else: player.sprite.image.fill('red')
这里我们先用普通的精灵碰撞检测(矩形碰撞),如果发生了矩形碰撞,在使用蒙版碰撞将pygame.sprite.collide_mask作为参数传入pygame.sprite.spritecollide。
因为矩形检测比蒙版检测速度快很多,这样做可以减少蒙版检测的次数,提高效率。
https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollide
完整代码:
import pygame, sys class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.Surface((40,40)) self.image.fill('red') self.rect = self.image.get_rect(center = (300,300)) self.mask = pygame.mask.from_surface(self.image) def update(self): if pygame.mouse.get_pos(): self.rect.center = pygame.mouse.get_pos() class Obstacle(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load('alpha.png').convert_alpha() self.rect = self.image.get_rect(center = (400,400)) self.mask = pygame.mask.from_surface(self.image) # pygame setup pygame.init() screen = pygame.display.set_mode((800,800)) clock = pygame.time.Clock() # group setup player = pygame.sprite.GroupSingle(Player()) obstacle = pygame.sprite.GroupSingle(Obstacle()) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() screen.fill('white') obstacle.draw(screen) # updating and drawing player.update() player.draw(screen) # collision if pygame.sprite.spritecollide(player.sprite,obstacle,False): if pygame.sprite.spritecollide(player.sprite,obstacle,False,pygame.sprite.collide_mask): player.sprite.image.fill('green') else: player.sprite.image.fill('red') pygame.display.update() clock.tick(60)
图片轮廓
将字母α \alphaα的轮廓变成橘色。
我们需要:
从surface 创建mask.
将mask变成surface.
使用2中的surface创建轮廓(silhouette)
显示轮廓。
import pygame,sys pygame.init() screen = pygame.display.set_mode((800,800)) clock = pygame.time.Clock() # creating the obstacle obstacle_surf = pygame.image.load('alpha.png').convert_alpha() obstacle_pos = (100,100) # 1. surface -> mask obstacle_mask = pygame.mask.from_surface(obstacle_surf) # 2. mask -> surface new_obstacle_surf = obstacle_mask.to_surface() # 与colorkey相同的像素变透明 new_obstacle_surf.set_colorkey((0,0,0)) # 4. filling in the surface with a color surf_w,surf_h = new_obstacle_surf.get_size() for x in range(surf_w): for y in range(surf_h): if new_obstacle_surf.get_at((x,y))[0] != 0: new_obstacle_surf.set_at((x,y),'orange') while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() screen.fill('grey') # complex way for a outline offset = 4 screen.blit(new_obstacle_surf,(obstacle_pos[0] + offset,obstacle_pos[1])) # right screen.blit(new_obstacle_surf,(obstacle_pos[0] - offset,obstacle_pos[1])) # left screen.blit(new_obstacle_surf,(obstacle_pos[0], obstacle_pos[1] - offset)) # top screen.blit(new_obstacle_surf,(obstacle_pos[0], obstacle_pos[1] + offset)) # bottom screen.blit(new_obstacle_surf,(obstacle_pos[0] + offset, obstacle_pos[1] - offset)) # topright screen.blit(new_obstacle_surf,(obstacle_pos[0] + offset, obstacle_pos[1] + offset)) # bottomright screen.blit(new_obstacle_surf,(obstacle_pos[0] - offset, obstacle_pos[1] + offset)) # bottomleft screen.blit(new_obstacle_surf,(obstacle_pos[0] - offset, obstacle_pos[1] - offset)) # topleft screen.blit(obstacle_surf,obstacle_pos) # simple way to create an outline from a mask # for point in obstacle_mask.outline(): # x = point[0] + obstacle_pos[0] # y = point[1] + obstacle_pos[1] # pygame.draw.circle(screen,'red',(x,y),1) pygame.display.update() clock.tick(60)
重叠部分着色
- 使用
overlap_mask
获得重叠部分的mask - 重新设置重叠部分mask的颜色。
import pygame,sys pygame.init() screen = pygame.display.set_mode((800,800)) clock = pygame.time.Clock() # ship setup ship_surf = pygame.image.load('ship.png').convert_alpha() ship_overlay_surf = pygame.image.load('ship.png').convert_alpha() ship_rect = ship_surf.get_rect(center = (300,300)) ship_mask = pygame.mask.from_surface(ship_surf) # obstacle setup obstacle_surf = pygame.image.load('alpha.png').convert_alpha() obstacle_pos = (100,100) obstacle_mask = pygame.mask.from_surface(obstacle_surf) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() screen.fill('white') # obstacle screen.blit(obstacle_surf,obstacle_pos) # moving part if pygame.mouse.get_pos():ship_rect.center = pygame.mouse.get_pos() screen.blit(ship_surf,ship_rect) # mask coloring offset_x = obstacle_pos[0] - ship_rect.left offset_y = obstacle_pos[1] - ship_rect.top if ship_mask.overlap(obstacle_mask,(offset_x,offset_y)): new_mask = ship_mask.overlap_mask(obstacle_mask,(offset_x,offset_y)) new_surf = new_mask.to_surface() new_surf.set_colorkey((0,0,0)) surf_w, surf_h = new_surf.get_size() for x in range(surf_w): for y in range(surf_h): if new_surf.get_at((x,y))[0] != 0: new_surf.set_at((x,y),'orange') screen.blit(new_surf,ship_rect) pygame.display.update() clock.tick(60)