Pygame 遮罩

Pygame 遮罩

用途

解决不规则图形碰撞

示例

反例:
用矩形对象来检测两个圆的碰撞

# coding: utf-8
# 作者:爱编程的章老师
# 创建:2021/1/28 8:48 下午 
# 邮箱:slxxf000@163.com
# 微信:slxxfl
# 微信公众号:A卫隆少儿编程
# 格言:给自己的生活增加一份向上的力,每都进步一点点


import pygame
from sys import exit

WIDTH = 800
HEIGHT = 800

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("没用遮罩")
clock = pygame.time.Clock()

# 红色圆
red_circle = pygame.Surface((200, 200), pygame.SRCALPHA)
pygame.draw.circle(red_circle, "red", (100, 100), 100)
# 红色圆的位置矩形
red_circle_rect = pygame.Rect(600, 0, 200, 200)  # 初位置位于屏幕左上角

# 蓝色圆
blue_circle = pygame.Surface((200, 200), pygame.SRCALPHA)
pygame.draw.circle(blue_circle, "blue", (100, 100), 100)
# 蓝色圆的位置
blue_circle_rect = pygame.Rect(0, 600, 200, 200)  # 初位置位于屏幕右下角

screen.blit(red_circle, red_circle_rect)
screen.blit(blue_circle, blue_circle_rect)
pygame.display.update()


while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
    if not red_circle_rect.colliderect(blue_circle_rect):
        red_circle_rect.move_ip(-1, 1)
        blue_circle_rect.move_ip(1, -1)
        screen.fill("black")
        screen.blit(red_circle, red_circle_rect)
        screen.blit(blue_circle, blue_circle_rect)
        pygame.display.update()

    # 设置帧率
    clock.tick(60)




效果图:
在这里插入图片描述
可以看到,当两个圆所在的矩形的角落发生碰撞的时候,就判定为碰撞成功.但这个显然不是我们想要的结果.
因此,对于圆(或其他不规则的形状)不能简单的用矩形来判定碰撞

遮罩的应用:

# coding: utf-8
# 作者:爱编程的章老师
# 创建:2021/1/28 8:48 下午 
# 邮箱:slxxf000@163.com
# 微信:slxxfl
# 微信公众号:A卫隆少儿编程
# 格言:给自己的生活增加一份向上的力,每都进步一点点


import pygame
from sys import exit

WIDTH = 800
HEIGHT = 800
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("遮罩")
clock = pygame.time.Clock()

# 红色圆
red_circle = pygame.Surface((200, 200), pygame.SRCALPHA)
pygame.draw.circle(red_circle, "red", (100, 100), 100)
# 红色圆的位置矩形
red_circle_rect = pygame.Rect(600, 0, 200, 200)  # 初位置位于屏幕左上角
m1 = pygame.mask.from_surface(red_circle)  # 生成红球的遮罩 

# 蓝色圆
blue_circle = pygame.Surface((200, 200), pygame.SRCALPHA)
pygame.draw.circle(blue_circle, "blue", (100, 100), 100)
# 蓝色圆的位置
blue_circle_rect = pygame.Rect(0, 600, 200, 200)  # 初位置位于屏幕右下角
m2 = pygame.mask.from_surface(blue_circle)  # 生成蓝球的遮罩

screen.blit(red_circle, red_circle_rect)
screen.blit(blue_circle, blue_circle_rect)
pygame.display.update()

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()

    offset = blue_circle_rect.x - red_circle_rect.x, blue_circle_rect.y - red_circle_rect.y
    p = m1.overlap(m2, offset)
    if not p:
        red_circle_rect.move_ip(-1, 1)
        blue_circle_rect.move_ip(1, -1)
        screen.fill("black")
        screen.blit(red_circle, red_circle_rect)
        screen.blit(blue_circle, blue_circle_rect)
        pygame.display.update()
    # 设置帧率
    clock.tick(60)

效果图:
在这里插入图片描述
可以看到,当我们用了遮罩的时候,两个是真实的碰到了一起才停止移动

代码解析

使用遮罩的基本流程:

  1. 对于一个surface对像生成一个遮罩
mask1 = pygame.mask.from_surface(surface,threshold = 127)

当surface对象是基于set_colorkey 透明时,第二个参数会忽略
当surface对象是基于每象素透明时,第二个参数是是一个阈值.如果该象的alpha的值>127则不透明,<127则透明
透明处的值为1,不透明的值为0

  1. 判定两个mask的碰撞情况:
mask1.overlap(mask2, offset)

offset = rect2.x - rect1.x , rect2.y - rect1.y
offset:第二个遮罩对应的矩形的左上角与第一个遮罩对应的矩形的左上角的相对位置.
因此,按上面的公式进行计算即可

上式代码会返回一个值.这个值为第二个遮罩与第一个遮罩的碰撞点的相对于第一个遮罩的左上角的坐标:
如rect1.x = 10, rect1.y = 20
p = (20, 20)
即这个点在 第一个矩形左上的右侧20 象素,下方20象素的位置
即实际位置为(30,40)
如果没有碰撞,则返回一个None的值

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的章老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值