检测可以旋转的两个精灵的碰撞

我在2D Java游戏中遇到碰撞检测问题。

通常,我要做的是为可能与其他对象冲突的对象创建一个getBounds()方法。 此方法将返回一个new Rectangle(x,y,width,height) ,其中xy是精灵左上角的坐标, widthheight是精灵的宽度和高度。

但是在我正在进行的游戏中,有一个由用户控制的“坦克”。 只要玩家握住左或右箭头按钮之一,该坦克的精灵就会旋转 。 换句话说,它可以旋转到任何角度。 坦克的精灵是一个矩形。

所以我不能简单地做我在这种情况下经常做的事情。

如何检测这种精灵的碰撞? 谢谢

很多将取决于您如何管理您的对象,但……

旋转....

 import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.GeneralPath; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class RotateTest { public static void main(String[] args) { new RotateTest(); } public RotateTest() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private Rectangle rect01; private Rectangle rect02; private int angle = 0; public TestPane() { rect01 = new Rectangle(0, 0, 100, 100); rect02 = new Rectangle(0, 0, 100, 100); Timer timer = new Timer(40, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { angle++; repaint(); } }); timer.start(); } @Override public Dimension getPreferredSize() { return new Dimension(250, 250); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); int width = getWidth(); int height = getHeight(); AffineTransform at = new AffineTransform(); int center = width / 2; int x = center + (center - rect01.width) / 2; int y = (height - rect01.height) / 2; at.translate(x, y); at.rotate(Math.toRadians(angle), rect01.width / 2, rect01.height / 2); GeneralPath path1 = new GeneralPath(); path1.append(rect01.getPathIterator(at), true); g2d.fill(path1); g2d.setColor(Color.BLUE); g2d.draw(path1.getBounds()); at = new AffineTransform(); x = (center - rect02.width) / 2; y = (height - rect02.height) / 2; at.translate(x, y); at.rotate(Math.toRadians(-angle), rect02.width / 2, rect02.height / 2); GeneralPath path2 = new GeneralPath(); path2.append(rect01.getPathIterator(at), true); g2d.fill(path2); g2d.setColor(Color.BLUE); g2d.draw(path2.getBounds()); Area a1 = new Area(path1); Area a2 = new Area(path2); a2.intersect(a1); if (!a2.isEmpty()) { g2d.setColor(Color.RED); g2d.fill(a2); } g2d.dispose(); } } } 

基本上,它的作用是,它创建了一个RectanglePathIterator ,它允许我在不影响原始形状的情况下对形状应用AffineTransformation …不知道这是否重要,但这就是我做的它…

然后我创建了一个允许我绘制PathIteratorGeneralPath

现在,时髦的位……

我创建了两个Area ,每个GeneralPath代表我想要检查的每个对象。 然后我使用Areaintersect方法,它生成一个Area ,表示两个对象的交点,然后检查这个结果是否为空。

如果它是空的,它不相交,如果它不是(空的),它们会触摸。

玩得开心;)

您可以使用多边形而不是矩形。

http://docs.oracle.com/javase/7/docs/api/java/awt/Polygon.html

然而,这将手动计算(x,y)角。 有可能通过旋转Rectangle来构造形状,但这至少可以起作用。 它有一个getBounds()方法。

如果你保留坦克可以在ArrayList中运行的所有对象,并且只是在一个单独的线程中的循环中使用for语句来确定坦克是否已经击中了什么,该怎么办? 例如,为每个对象创建一个类,比如类Wall(),并保持x,y变量可用。 将Wall()放入ArrayList,在本例中为tank。 然后在for循环中,在while循环中:EC

 while(true) { for(int i = 0; i < tanks.size(); i++) { //Do the code to determine if the tank has hit something. if(tanks.get(i).x => tank.x) //Do whatever } } 

当然要根据你的需要进行调整,但想法是一样的。 如果物体与水箱相交,反之亦然,那就做你想做的事。 总结一下,只需检查油箱占用的区域,看看该区域是否与另一个物体相交。

实际上,甚至更好:

我假设你使用paint()方法? 每当你更新组件时,只需添加一些基本上与我刚才所说的相同的代码,检查该区域是否与if()语句相交。 EC:

  if(tanks.get(i).x => tank.x || tanks.get(i).y => tank.y) DO SOMETHING 

当然,再次调整if()以满足您的需求