我在2D Java游戏中遇到碰撞检测问题。
通常,我要做的是为可能与其他对象冲突的对象创建一个getBounds()方法。此方法将返回new Rectangle(x,y,width,height)
,其中x
和y
是精灵左上角的坐标,width
和height
是精灵的宽度和高度。
但是在我正在进行的游戏中,有一个由用户控制的“坦克”。只要玩家持有左箭头或右箭头按钮之一,该坦克的精灵就会旋转。换句话说,它可以旋转到任何角度。坦克的精灵是一个矩形。
所以我不能简单地做我在这种情况下经常做的事情。
如何检测与此类精灵的碰撞? 感谢
答案 0 :(得分:4)
很多将取决于您如何管理对象,但......
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();
}
}
}
基本上,它的作用是,它会创建PathIterator
的{{1}},这样我就可以在不影响原始形状的情况下将Rectangle
应用于形状...不要知道这是否重要,但这就是我做的方式......
然后我创建了一个AffineTransformation
,它允许我绘制GeneralPath
。
现在,时髦的位......
我创建两个PathIterator
,每个Area
一个代表我要检查的每个对象。然后我使用GeneralPath
的{{1}}方法生成Area
,表示两个对象的交点,然后检查此结果是否为空。
如果它是空的,它不相交,如果它不是(空的),它们会触摸。
玩得很开心;)
答案 1 :(得分:0)
如果保留坦克可以在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()以满足您的需求
答案 2 :(得分:0)
您可以使用多边形而不是矩形。
http://docs.oracle.com/javase/7/docs/api/java/awt/Polygon.html
然而,这将手动计算(x,y)角。有可能通过旋转Rectangle来构造一个形状,但这至少可以起作用。它有一个getBounds()
方法。