曾经做过一款捕鱼游戏,有的鱼比较大比较长,图片中的透明区域较多,因为碰撞检测是以鱼和子弹的中心点距离小于一定值来判断的,所以不精确。若是根据子弹的中心点是否在鱼的区域内,因为鱼有透明像素,可能子弹在鱼的透明区域就会判断会碰撞,所以视觉上更不精确。
今天就讲一下如何给这种带透明区域的物体做精确的碰撞检测。
以1024x1024尺寸的纹理为例。
在读取图片时保存每个像素点的模版值,模版1表示非空白,模版值0表示空白,模版值根据alpha值来生成,当alpha低于阈值则模版值为0。
常规方法
1,以uint8来保存纹理每个像素点模版值,单张纹理保存模版值则所需内存为1024x1024=1M。同时记录模版的宽高值。
2,判断a物体的中心点是否与b物体碰撞。获取a物体中心点在b物体中的位置,位置取整即得在b模版中的位置,然后根据位置取得模版值,模版值1表示碰撞,模版值0表示未碰撞。
3,判断a物体与b物体相交区域的碰撞情况。获取a物体和b物体的相交区域的模版区域area_a和area_b,循环遍历相交的模版区域,把2个物体同一位置的模版值相乘得到该位置的碰撞结果(1为碰撞,0为未碰撞),最终得到相交区域的碰撞结果。其计算复杂度为相交区域的宽x高。
优化方法
1,以位来保存纹理每个像素点模版值,单张纹理保存模版值则所需内存为1024x1024/8=1/8M。同时记录模版的宽高值。较常规方法大大降低所需内存,整个游戏即使同存储100张1024x1024的纹理的模版值也才12.5M,消耗的内存非常少。
2,判断a物体的中心点是否与b物体碰撞。获取a物体中心点在b物体中的位置,位置取整即得在b模版中的位置,然后根据位置取得模版值,模版值1表示碰撞,模版值0表示未碰撞。计算复杂度与常规方法一致。
3,判断a物体与b物体相交区域的碰撞情况。获取a物体和b物体的相交区域的模版区域area_a和area_b,用32位的位运算每次计算area_a和area_b32个模版值的按位与的结果。相较与常规方法,计算复杂度降为1/32。