碰撞检测与复杂的形状

我想制作一个游戏,每个级别从图像加载。 我想在Photoshop中绘制整个关卡,然后将其设置为背景,并让玩家走过去。 我想要另一个看不见的形象,在我想要碰撞的所有地方都会变成黑色。

我不想使用瓷砖的原因,这是矩形碰撞等更容易,是因为会有复杂的angular落,并不是所有的东西都是矩形的。

这是一个好主意,可以轻松做到吗? 这会是一个大CPU的猪还是有更好的方法来做到这一点?

关卡图像

关卡图像

障碍以红色显示

红色的障碍

会有复杂的angular落,并不是所有的东西都是矩形的。

这可以通过绘制和处理ShapeArea实例来实现。 例如

  • 黄色是一个有点animation的“玩家”。
  • 图像的边界表示包含玩家path的墙(它反弹掉)。
  • 不碰撞时,障碍物涂成绿色,否则涂上红色。

ShapeCollision

 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); } } 

编辑

使它检测到所有的红色,并将其设置为碰撞界限

在启动时,使用“ 平滑锯齿形path”问题中看到的源代码获取红色像素的轮廓(请参阅getOutline(Color target, BufferedImage bi)方法)。 将该Area存储为启动时的单个障碍物。