我正在编写游戏,我想将带有透明边框(精灵)的图像与圆形碰撞。
通过检查与不透明像素的碰撞,很容易知道圆圈是否与图像重叠。
我遇到的问题是要知道法线角度以便反弹。
我需要一个库(Java)或算法,给定一个图像,它将返回一个数组,其中包含图像边界处的像素,这样我就可以找到表面两点之间的斜率。
有没有我可以学习的库/算法/代码片段?
我正在编写游戏,我想将带有透明边框(精灵)的图像与圆形碰撞。
通过检查与不透明像素的碰撞,很容易知道圆圈是否与图像重叠。
我遇到的问题是要知道法线角度以便反弹。
我需要一个库(Java)或算法,给定一个图像,它将返回一个数组,其中包含图像边界处的像素,这样我就可以找到表面两点之间的斜率。
有没有我可以学习的库/算法/代码片段?
这是一个简单的方法:
0
从所有透明像素和所有非透明像素的原始图像创建蒙版1
(x,y)
然后,通过从像素中减去每个像素(即0
或1
)(x+1,y+1)
并取绝对值,对您的蒙版执行简单的边缘检测。
这将为您1
提供图像边缘的像素和0
其他任何地方的像素。
注意:这种方法本质上等同于将图像视为二维函数并计算其梯度。边缘是强度表面的陡峭部分(对应于大梯度值)。这是有关基于梯度的边缘检测的更多信息。
这是一个示例图像:
首先屏蔽所有不透明的像素:
然后将图像向下移动一个像素,然后将其从自身中减去。
这将创建下面的图像。现在只需用 value 读出矩阵索引1
。
那是你的边缘像素数组。
注意:如果您的图像包含内部透明像素,此技术也会发现内部边缘,这对您来说可能是也可能不是问题......
这是我长期以来实施的:(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 + "]";
}
}
使用该算法创建的图像将是: