Java 游戏中多个物体之间的碰撞检测?
我试图理解如何实现多个对象之间的碰撞检测。 我的项目检测到对象之间的碰撞,但它在碰撞后立即崩溃 这是我的主类,带有Java 游戏中多个物体之间的碰撞检测?,java,multithreading,swing,collision-detection,Java,Multithreading,Swing,Collision Detection,我试图理解如何实现多个对象之间的碰撞检测。 我的项目检测到对象之间的碰撞,但它在碰撞后立即崩溃 这是我的主类,带有JFrame和main循环: public class Window { public static void main(String[] args){ GamePanel gamepanel = new GamePanel(); JFrame f = new JFrame("Multiple Collision Detection"); f.setSize
JFrame
和main循环
:
public class Window {
public static void main(String[] args){
GamePanel gamepanel = new GamePanel();
JFrame f = new JFrame("Multiple Collision Detection");
f.setSize(400, 400);
f.add(gamepanel);
f.setVisible(true);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
while(true){
gamepanel.repaint();
gamepanel.update();
try{
Thread.sleep(10);
}catch(Exception e){
System.out.println("Main Loop Error");
}
}
}
}
然后我有两门课,一门给玩家,一门给敌人:
玩家:
public class Player {
int x = 175, y = 175, w = 50, h = 50, dx = 0, dy = 0;
Rectangle rect;
public void paint(Graphics g) {
rect = new Rectangle(x, y, w, h);
g.setColor(Color.black);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
g.setColor(Color.CYAN);
g.drawRect(x, y, w, h);
}
public void setDx(int dx) {
this.dx = dx;
}
public void setDy(int dy) {
this.dy = dy;
}
public void move() {
x += dx;
y += dy;
}
public void update() {
move();
}
}
敌人:
public class Enemy {
int x, y, w = 35, h = 35;
Rectangle rect;
public Enemy(int x, int y) {
this.x = x;
this.y = y;
}
public void paint(Graphics g) {
rect = new Rectangle(x, y, w, h);
g.setColor(Color.red);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
public void update() {
}
}
我有一个EnemyManager类,它通过列表
吸引了多个敌人(在本例中为3):
public class EnemyManager {
Player player = new Player();
Rectangle playerrect;
Rectangle enemyrect;
List<Enemy> enemies = new ArrayList<Enemy>();
public void paint(Graphics g) {
enemies.add(new Enemy(20, 20));
enemies.add(new Enemy(320, 20));
enemies.add(new Enemy(20, 320));
for (Enemy e : enemies) {
e.paint(g);
}
}
public void update() {
}
}
当游戏检测到玩家和敌人之间发生碰撞时,会将“碰撞”打印到控制台,但之后会出现以下错误:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at GamePanel.checkPlayerEnemyCollision(GamePanel.java:22)
at GamePanel.update(GamePanel.java:34)
at Window.main(Window.java:20)
有人知道问题是什么,也许知道如何解决吗
提前感谢。我尝试了你的程序,但使用A、W、S、D键无法移动任何东西。但是,我确实像你所说的那样,在for循环点上出现了并发mod异常 尝试将所有增强循环更改为正常循环。例如,在
for (Enemy e : enemies) {
e.paint(g);
}
改为:
for (int i = 0; i < enemies.size(); i++)
enemies.get(i).paint(g);
for(int i=0;i
这样做之后,我再也没有得到错误了
如果在某些时间对数组执行某些操作,则增强的for循环会导致错误。但我不确定为什么会出现这种情况,因为我不太熟悉Java中图形在幕后的工作方式。您得到的是ConcurrentModificationException,这意味着您试图在一个线程中修改集合,而在另一个线程中对其进行迭代(如果在迭代时尝试修改集合,也可能在单个线程中发生,但这里不是这样) 这一切都源于这样一个事实:你没有注意到你的事件发生在哪个线程中。你有两个活动线程,不管你意识到与否 线程#1是程序的主线程,应用程序从这里开始 线程#2是Swing EDT,所有用户操作都从该线程启动 在从Swing EDT对集合进行迭代时,您似乎正在尝试从主线程更新域模型。您需要同步访问,或者通过稍后将其包装在调用中使所有更新在EDT上执行:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
gamepanel.repaint();
gamepanel.update();
}
});
请注意,我不知道在循环+线程.sleep中简单地使用上面的代码片段是正确的操作,因为我没有通读您的所有逻辑。至少您应该阅读一个从事件调度程序线程调用的
。您可以使用此方法修改列表
event dispatcher thread
-> GamePanel.paint
-> EnemyManager.paint
-> enemies.add
但是,您可以通过GamePanel中的“foreach”循环使用列表的迭代器。checkPlayerEnemyCollision
:
for(Enemy e : enemymanager.enemies)
但是ArrayList的迭代器
会失败,如果您在创建迭代器后修改列表,并且出现异常
由于列表修改和迭代器可以从不同的线程使用,因此它们很容易相互干扰,例如:
paint
你的设计有点瑕疵: 调用
paint
时,您几乎没有控制权,正如方法名称所示,它用于绘制。不要更改此方法中的数据,只需绘制它即可
重新设计你的程序,记住这一点(例如,可以先阅读教程)
您仍然需要从不同于修改列表的线程读取敌方
列表。请使用列表的获取
方法而不是迭代器,并记住,列表的大小可以更改,因此您需要稍微同步一些内容。如果线程“保留”一个允许他们访问的特定索引范围。这不是一个合适的(或正确的修复)。它不抛出ConcurrentModificationException的唯一原因是因为您没有活动的迭代器。相反,它将在几种糟糕的情况下结束,例如1)在同一个敌人身上画两次2)IndexOutOfBounds例外,当他超过限制时3)不画敌人,因为他们在他到达最后一个索引后被添加
for(Enemy e : enemymanager.enemies)