Pixel-Perfect Collision Detection Android

DRi*_*FTy 13 java android bitmap collision-detection

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

Che*_*mon 14

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

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

迭代所有这些像素,并检查两个对象中是否填充了像素.如果它们中的任何一个是,那么你就会发生碰撞.

如果矩形与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;
     }
  }
}
Run Code Online (Sandbox Code Playgroud)


Jan*_*sen 14

我已将我的代码基于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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的分享!如果有人看到他们遇到这篇文章,那么有一个很好的代码示例会很好.我不了解你,但我认为很难找到人们为Android或Java做像素碰撞检测的例子.我认为这将是一个受欢迎的主题...... (2认同)

itm*_*kel 6

我更改了arcones的代码,因此该方法适用于Bitmaps而不是Sprites.

import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;


public class KollisionsErkennung {

/**
 * @param bitmap1 First bitmap
 * @param x1 x-position of bitmap1 on screen.
 * @param y1 y-position of bitmap1 on screen.
 * @param bitmap2 Second bitmap.
 * @param x2 x-position of bitmap2 on screen.
 * @param y2 y-position of bitmap2 on screen.
 */
public static boolean isCollisionDetected(Bitmap bitmap1, int x1, int y1,
        Bitmap bitmap2, int x2, int y2) {

    Rect bounds1 = new Rect(x1, y1, x1+bitmap1.getWidth(), y1+bitmap1.getHeight());
    Rect bounds2 = new Rect(x2, y2, x2+bitmap2.getWidth(), y2+bitmap2.getHeight());

    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 bitmap1Pixel = bitmap1.getPixel(i-x1, j-y1);
                int bitmap2Pixel = bitmap2.getPixel(i-x2, j-y2);
                if (isFilled(bitmap1Pixel) && isFilled(bitmap2Pixel)) {
                    return true;
                }
            }
        }
    }
    return false;
}

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;
}
}
Run Code Online (Sandbox Code Playgroud)

根据我的需要,它足够快.