像素完美碰撞检测安卓

2022-09-04 06:04:48

好吧,所以我正在Android上开发一款游戏。我需要实现像素完美碰撞检测。我已经在每个图像周围设置了边界框,每个边界框都经过转换以匹配图像的当前旋转。这一切都很好。我还将每个位图的像素数据存储在数组中。有人可以帮我找出最有效的方法来检测像素是否重叠吗?提前感谢您的任何帮助!


答案 1

基本思想是为每个对象创建一个位掩码,在每个像素中指示对象是否确实存在。然后比较两个对象的位掩码的每个像素。

您可以通过计算两个边界框重叠的矩形区域来最小化需要检查的像素数。此区域内的像素是您需要检查的像素。

循环访问所有这些像素,并检查该像素是否在两个对象中都已填充。如果其中任何一个是,那么你就有碰撞了。

如果矩形与 x/y 轴对齐,要查找重叠,请查找重叠的左侧、右侧、顶部和底部。它看起来像这样(我可能搞砸了边缘情况,没有尝试过):

int left = max(obj1.left, obj2.left)
int right = min(obj1.right, obj2.right)
int top = min(obj1.top, obj2.top)
int bottom = max(obj1.bottom, obj2.bottom)

for (int x = left; x < right; x++) {
  for (int y = top; y < bottom; y++) {
     if (obj1.isFilled(x,y) && obj2.isFilled(x,y)) {
        return true;
     }
  }
}

答案 2

我的代码基于Mayra的例子,并进行了位图像素碰撞处理。我希望这会有所帮助。

public class CollisionUtil {
    public static boolean isCollisionDetected(Sprite sprite1, Sprite sprite2){
        Rect bounds1 = sprite1.getBounds();
        Rect bounds2 = sprite2.getBounds();

        if( Rect.intersects(bounds1, bounds2) ){
            Rect collisionBounds = getCollisionBounds(bounds1, bounds2);
            for (int i = collisionBounds.left; i < collisionBounds.right; i++) {
                for (int j = collisionBounds.top; j < collisionBounds.bottom; j++) {
                    int sprite1Pixel = getBitmapPixel(sprite1, i, j);
                    int sprite2Pixel = getBitmapPixel(sprite2, i, j); 
                    if( isFilled(sprite1Pixel) && isFilled(sprite2Pixel)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private static int getBitmapPixel(Sprite sprite, int i, int j) {
        return sprite.getBitmap().getPixel(i-(int)sprite.getX(), j-(int)sprite.getY());
    }

    private static Rect getCollisionBounds(Rect rect1, Rect rect2) {
        int left = (int) Math.max(rect1.left, rect2.left);
        int top = (int) Math.max(rect1.top, rect2.top);
        int right = (int) Math.min(rect1.right, rect2.right);
        int bottom = (int) Math.min(rect1.bottom, rect2.bottom);
        return new Rect(left, top, right, bottom);
    }

    private static boolean isFilled(int pixel) {
        return pixel != Color.TRANSPARENT;
    }
}

推荐