python像素级碰撞基本理论

在进行游戏开发的过程中,最完美的碰撞检测就是像素级碰撞检测。图像是由像素点组成的,每个像素点有4个值,分别是RGBA。
R代表红色通道,G代表绿色通道,B代表蓝色通道,A代表透明度通道。
如果A的值为0,代表这个像素点是看不见的,即完全透明。如果A的值为255,代表这个像素点是完全不透明的。
为了描述方便,这里假设有img1,它是一个png图形。它在一个屏幕中,它的最小矩形即rect1是可以求出来的。
用np.array(Image.open(img1)),返回二维阵列为im1。
我们不需要颜色信息,只要知道每个像素点到底是透明的还是不透明的即可,所以我们通过alpha1 = im1[:, :, 3]就能提取所有像素点的透明度值。还假设有img2,用np.array(Image.open(img2))返回的二维阵列为im2,它的最小绑定矩形为rect2,用同样的式子也能得到alpha2。

如果要检测img1和img2有不透明像素重叠,那么首先应该检测它们有没有重叠的矩形区域。
如果有矩形重叠,则取这个重叠区域,假设为overlapped_rect。
注意这里的rect1和rect2及overlapped_rect都是相对于整个屏幕的,如下图所示:

为了描述方便,假设重叠区域宽高都为10。把overlapped_rect矩形减去rect1就能求出重叠区域相对于rect1的子矩形。
我们把它叫sub_rect1。把它解包为left,top,right,bottom。再通过alpha1 = alpha[top:bottom,left:right],
就能求出重叠区域每个像素的透明度值。就像下面这样所示:

[[255 255 255 251   0   0   0   0   0   0]
 [255 255 255 251   0   0   0   0   0   0]
 [255 255 255 251   0   0   0   0   0   0]
 [251 251 251 251   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 251 251 251 251 251   0]
 [  0   0   0   0 251 251 251 251 251   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]

我们认为大于127透明度的值为不透明,所以我们把上面的进行mask1 = alpha > 127这个运算,得到以下结果:

[[1 1 1 1 0 0 0 0 0 0]
 [1 1 1 1 0 0 0 0 0 0]
 [1 1 1 1 0 0 0 0 0 0]
 [1 1 1 1 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 1 1 1 1 0]
 [0 0 0 0 1 1 1 1 1 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]

我们对img2也进行同样的处理,也会得到一个mask,它就包括了图像在这个子区域的透明度信息。我们把它叫遮罩,img2的mask就取名为mask2。

假设mask2如下所示:

[[0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 1 1 1 1 0]
 [0 0 0 0 1 1 1 1 1 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]

如果把mask1和mask2进行相加得到mask3,那么在mask3中的值就会有2,这就说明有不透明像素重叠!
通过array = np.argwhere(mask3 == 2)就能得出所有值为2的行列号。

接下来,通过array[0]就能得到第一个碰撞点的行列号。当然,这个行列号是相对于重叠区域的行列号。
不过,我们把行列号加上重叠区域的左上角坐标就能得到碰撞点的坐标了。
当然,也能求出这个碰撞点在图形1和图形2上的像素值,只不过是一个求坐标的过程,只要加上它们的sub_rect1的坐标。
再用im的getpixel就能得到像素值,这样就能进行颜色碰撞了。

关于李兴球

李兴球的博客是Python创意编程原创博客
此条目发表在python, 杂谈分类目录。将固定链接加入收藏夹。