Java 复杂形状的碰撞检测
我想做一个游戏,有每一个级别的图像加载。 我想在Photoshop中绘制整个关卡,然后将其设置为背景,让玩家在其上行走。 我希望另一个不可见的图像越过顶部,在所有我想碰撞的地方都是黑色的 我不想使用平铺的原因是因为会有复杂的角点,而不是所有的东西都是矩形的,因为矩形的碰撞更容易 这是一个好主意吗?有可能很容易做到吗? 这是一个巨大的CPU消耗,还是有更好的方法来做到这一点 水平图像 红色显示的障碍物 …将有复杂的角,并非所有的东西都是矩形 这可以通过绘制和处理形状和面积实例来实现。例如 黄色是一个小小的动画“播放器”。 图像的边界表示包含从其上反弹的玩家路径的墙。 未发生碰撞时,障碍物漆成绿色,否则漆成红色。 编辑 使其检测所有红色并将其设置为碰撞边界Java 复杂形状的碰撞检测,java,image,awt,collision,java-2d,Java,Image,Awt,Collision,Java 2d,我想做一个游戏,有每一个级别的图像加载。 我想在Photoshop中绘制整个关卡,然后将其设置为背景,让玩家在其上行走。 我希望另一个不可见的图像越过顶部,在所有我想碰撞的地方都是黑色的 我不想使用平铺的原因是因为会有复杂的角点,而不是所有的东西都是矩形的,因为矩形的碰撞更容易 这是一个好主意吗?有可能很容易做到吗? 这是一个巨大的CPU消耗,还是有更好的方法来做到这一点 水平图像 红色显示的障碍物 …将有复杂的角,并非所有的东西都是矩形 这可以通过绘制和处理形状和面积实例来实现。例如 黄色是一
启动时,使用问题中显示的源获取红色像素的轮廓。请参见getOutlineColor目标BuffereImage bi方法。启动时,将该区域存储为单个障碍物。将有复杂的拐角,并且并非所有东西都是矩形。我认为这可以通过绘制和处理形状和面积实例来实现。实际上,你可以同时做这两件事:一个近似廉价的初始矩形碰撞检查,以快速排除大多数候选对象,以及一个更精确的后续检查,如果前一个成功的话。仔细查看不要忘记添加@Theodoroschatziganakis或任何通知他们的人一个新的评论。顺便问一下,你在回答谁?3个不同的人提出了3种不同的方法。为了“支持”我的方法,我添加了一个SSCCE。@Theodoroschatziganakis忘了提到您概述的方法是一个优秀的优化。也许这本可以/应该是一个答案。或者至少是其中的一部分。我从来没有在公认的答案中真正加载过100个形状的方法,或者许多大型形状的缩放和转换..感谢您花时间将这些写出来Andrew!这是我想要的款式。为了让这一切顺利进行,我需要在可行走的壁架周围创建一组这样的形状,在我看来这可能需要一些时间。如果我错了,请纠正我。因此,每个级别将有2个图像,我在上面发布的图像将显示在屏幕上。然后我会创建另一个这样的图像,让它检测所有的红色,并将其设置为碰撞边界。所以你只能在没有红色的地方行走。带有红色边界的图像不会显示,仅用于设置碰撞。对不起,我应该说得更清楚一点。谢谢安德鲁的帮助,希望我能把这个工作做好。如果我能投票支持你,我会的D+1这是到目前为止我最喜欢的碰撞检测答案。很好的例子,Andrew,谢谢。如何使用JFrame而不是JOptionPane?我在努力,但没有成功
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
class ShapeCollision {
private BufferedImage img;
private Area[] obstacles = new Area[4];
private Area walls;
int x;
int y;
int xDelta = 3;
int yDelta = 2;
/** A method to determine if two instances of Area intersect */
public boolean doAreasCollide(Area area1, Area area2) {
boolean collide = false;
Area collide1 = new Area(area1);
collide1.subtract(area2);
if (!collide1.equals(area1)) {
collide = true;
}
Area collide2 = new Area(area2);
collide2.subtract(area1);
if (!collide2.equals(area2)) {
collide = true;
}
return collide;
}
ShapeCollision() {
int w = 400;
int h = 200;
img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
final JLabel imageLabel = new JLabel(new ImageIcon(img));
x = w/2;
y = h/2;
//circle
obstacles[0] = new Area(new Ellipse2D.Double(40, 40, 30, 30));
int[] xTriangle = {330,360,345};
int[] yTriangle = {60,60,40};
//triangle
obstacles[1] = new Area(new Polygon(xTriangle, yTriangle, 3));
int[] xDiamond = {60,80,60,40};
int[] yDiamond = {120,140,160,140};
//diamond
obstacles[2] = new Area(new Polygon(xDiamond, yDiamond, 4));
int[] xOther = {360,340,360,340};
int[] yOther = {130,110,170,150};
// other
obstacles[3] = new Area(new Polygon(xOther, yOther, 4));
walls = new Area(new Rectangle(0,0,w,h));
ActionListener animate = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
animate();
imageLabel.repaint();
}
};
Timer timer = new Timer(50, animate);
timer.start();
JOptionPane.showMessageDialog(null, imageLabel);
timer.stop();
}
public void animate() {
Graphics2D g = img.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.BLUE);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
x+=xDelta;
y+=yDelta;
int s = 15;
Area player = new Area(new Ellipse2D.Double(x, y, s, s));
// Acid test of edge collision;
if (doAreasCollide(player,walls)) {
if ( x+s>img.getWidth() || x<0 ) {
xDelta *= -1;
}
if(y+s>img.getHeight() || y<0 ) {
yDelta *= -1;
}
}
g.setColor(Color.ORANGE);
for (Area obstacle : obstacles) {
if (doAreasCollide(obstacle, player)) {
g.setColor(Color.RED);
} else {
g.setColor(Color.GREEN);
}
g.fill(obstacle);
}
g.setColor(Color.YELLOW);
g.fill(player);
g.dispose();
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
new ShapeCollision();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}