查找具有透明环境的图像的边框像素(用于碰撞检测)

时间:2012-04-21 14:15:55

标签: java android sprite collision-detection transparent

我正在编写游戏,我想用透明边框(精灵)对着圆圈碰撞图像。

通过检查与不透明的像素的碰撞,很容易知道圆是否与图像重叠。

我遇到的问题是要知道正常角度才能弹跳。

我需要一个库(Java)或给定图像的算法,它会返回一个像素位于图像边界的数组,这样我就可以找到表面两点之间的斜率。

我可以从中学习任何库/算法/代码片段吗?

2 个答案:

答案 0 :(得分:8)

这是一个简单的方法:

从原始图像创建遮罩,其中所有透明像素均为0,所有非透明像素均为1

然后,通过从像素(x,y)中减去每个像素01(x+1,y+1))并取绝对值,对遮罩执行简单的边缘检测

这会在图片边缘为您提供1像素,在其他地方为0

注意:此方法基本上等同于将图像视为2d函数并计算其渐变。边缘是强度表面的陡峭部分(对应于大的梯度值)。以下是有关gradient-based edge detection的更多信息。


以下是一个示例图片:

Original Test Image

首先屏蔽所有非透明像素:

Image Mask

然后将图像向下移动一个像素并从中减去它。

这会创建下面的图像。现在只需读取值为1的矩阵索引。

这是你的边缘像素数组。

Edge Mask

注意:如果您的图片包含内部透明像素,此技术也会找到内部边缘,这对您来说可能是也可能不是问题......

答案 1 :(得分:3)

这是我实施的:(detectionStrength最好10)

public static List<Pixel> getEdges(Image image, int detectionStrength) {

    boolean[][] opaque = new boolean[image.getWidth(null)][image
            .getHeight(null)];
    LinkedList<Pixel> edges = new LinkedList<Pixel>();
    int rgb;

    /*
     * convert to BufferedImage to get individual pixel colors
     */
    BufferedImage bufferedImage;
    if (image instanceof BufferedImage)
        bufferedImage = (BufferedImage) image;
    else {
        bufferedImage = new BufferedImage(image.getWidth(null),
                image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        bufferedImage.createGraphics().drawImage(image, 0, 0, null);
    }

    for (int i = 0; i < opaque.length; i++) {
        for (int j = 0; j < opaque[i].length; j++) {
            rgb = bufferedImage.getRGB(i, j);
            opaque[i][j] = (rgb >> 24 & 0xFF) > detectionStrength; // transparency
        }
    }

    /*
     * If a pixel is opaque, but is surrounded, with at least one
     * transparent pixel, it is considered an edge.
     */
    for (int x = 0; x < opaque.length; x++) {
        for (int y = 0; y < opaque[x].length; y++) {
            if ((x == 0) || (x == opaque.length - 1) || (y == 0)
                    || (y == opaque[x].length - 1)) { // border pixel
                if (opaque[x][y]) // if opaque, it is automatically an edge,
                                    // no matter its surrounding...
                    edges.add(new Pixel(x, y, new Color(bufferedImage
                            .getRGB(x, y))));

            } else { // not a border pixel
                if (opaque[x][y]
                        && (!opaque[x - 1][y - 1] || !opaque[x][y - 1]
                                || !opaque[x + 1][y - 1]
                                || !opaque[x - 1][y] || !opaque[x + 1][y]
                                || !opaque[x - 1][y + 1]
                                || !opaque[x][y + 1] || !opaque[x + 1][y + 1]))
                    edges.add(new Pixel(x, y, new Color(bufferedImage
                            .getRGB(x, y))));
            }
        }
    }

    return edges;
}

Pixel类(只是Point的一个非常简单的扩展名):

public class Pixel extends Point implements Cloneable {

    private static final long serialVersionUID = -9053911985748552077L;

    public Color color;

    public Pixel(int x, int y, Color c) {
        super(x, y);
        color = c;
    }

    public Pixel(Pixel other) {
        super(other.x, other.y);
        color = other.color;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color newColor) {
        color = newColor;
    }

    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((color == null) ? 0 : color.hashCode());
        return result;
    }

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (!(obj instanceof Pixel))
            return false;
        Pixel other = (Pixel) obj;
        if (color == null) {
            if (other.color != null)
                return false;
        } else if (!color.equals(other.color))
            return false;
        return true;
    }

    public Object clone() {
        return new Pixel(x, y, color);
    }

    public String toString() {
        return "Pixel [color=" + color + ", x=" + x + ", y=" + y + "]";
    }
}

使用算法创建的图像将是:

StackOverflow logo