【问题标题】:Collision between player and enemy not working玩家和敌人之间的碰撞不起作用
【发布时间】:2015-05-20 03:12:31
【问题描述】:

我正在用 Java 制作游戏。并且玩家和敌人之间的碰撞无法正常工作。

我想要的是:当它们发生碰撞时,游戏结束了,我们需要进入游戏结束面板。 相反,它做了什么:敌人从玩家身上碾过,游戏继续进行。

我复制粘贴了一段代码,我真的希望有人能找出我做错了什么。

有关更多信息,玩家和敌人可以互相射击,并且碰撞有效。还有随机放置的障碍物,玩家和敌人都可以检测到。

当玩家与敌人发生碰撞时该怎么办:

for(Enemy enemy: enemies){
if (checkCollision(player, enemy)){
    player.dead = true;
    }
}

我在action执行函数中更新播放器:

if (!player.dead)
            player.redraw();

else
{
    spelTimer.stop();
    mainVenster.switchPanel(new GameOverPanel(mainVenster));}

函数 checkCollision(如果有帮助,请注明):

public boolean checkCollision(tanks.Game_Object object1, tanks.Game_Object object2){

    double dx = object1.x_pos - object2.x_pos;
    double dy = object1.y_pos - object2.y_pos;
    double distance = (dx*dx) + (dy*dy);
    double minDistance = (object1.r+object2.r);

    return (distance < minDistance*minDistance);    
}

编辑:x_pos 和 y_pos 是我的对象的中心坐标,r 是半径。

【问题讨论】:

  • 您的帧速率可能不够高,即使子弹 看起来 与播放器相交,程序也只能看到前一帧和后一帧。您可能想尝试将阈值 minDistance 增加到两倍大,看看情况如何。
  • 你是如何更新坐标的?
  • @bcr 我将尝试看看它提供了什么。不过我必须说,当我(玩家)向敌人或障碍物射击(并且我击中它们)时,它们会被移除。
  • @haifzhan 我设置了一个公共计时器计时器,延迟为 50 毫秒。我希望这是你想知道的?

标签: java


【解决方案1】:

你的玩家和敌人都用圆圈表示,对吧?这就是你的代码看起来的样子。在这种情况下,正确的碰撞公式是:

double dist = Math.sqrt(Math.sqr(obj1.x + ob1.radius - obj2.x - obj2.radius) + Math.sqr(obj1.y + ob1.radius - obj2.y - obj2.radius));

if (dist < (obj1.radius + obj2.radius)) {
  //collision
}

【讨论】:

  • 是的,我之前尝试过使用矩形,但这给我带来了困难,因为玩家和敌人都可以平移和旋转(它们是“坦克”)。我看了你说的,它看起来和我的 checkCollision 函数几乎一样(我的 x_pos 和 y_pos 是我的对象的中心坐标)?
  • 您应该首先提到的是,您的枢轴位于图纸的中心:)
【解决方案2】:

可能

public boolean checkCollision(tanks.Game_Object object1, tanks.Game_Object object2){

    double dx = object1.x_pos - object2.x_pos;
    double dy = object1.y_pos - object2.y_pos;
    double distance = (dx*dx) + (dy*dy);
    double minDistance = (object1.r+object2.r);

    return (Math.sqrt(distance) < minDistance);    
}

【讨论】:

  • 您从左上角开始计算。您需要从圆心计算
  • 我不认为添加 sqrt() 可以解决问题,但我会尝试!而@ControlAltDel 这段代码对不对,如果你看到 x_pos 和 y_pos 作为中心坐标?
  • @ml20 它可能无法解决问题。但他确实指出了一个没有人注意到的缺陷,似乎。 a^2 + b^2 = c^2。你的距离计算不正确,你需要得到 c 的平方根,在你的情况下是distance。如果没有解决问题,这绝对是解决问题的重要一步。
  • @NicholasEason 我没有在不等式的左侧添加平方根,而是在右侧添加了一个正方形。 ((dxdx) + (dydy)
【解决方案3】:

对于这种情况,我推荐Rectangle。当你创建一个Rectangle 时,你告诉它左上角,然后它在每个方向上延伸多远(就像你试图在你的方法中弄清楚一样)。然后你只需要用玩家更新Rectangle(使用rectangle.reshape(x,y,width,height)),并且在你当前检查碰撞的任何地方,用碰撞方法检查玩家的Rectangle而不是敌人的Rectangle

Rectangle r = new Rectangle(x,y,100,100);
Rectangle q = new Rectangle(x2,y2,100,100);
if(r.intersects(q)){
    //What occurs during collision
}

【讨论】:

  • 像这样抽象形状碰撞并不是最优的
  • @ControlAltDel 是的,看它是一个圆圈是有道理的......我不知道为什么我以前没有考虑过,但如果它们 100% 真的是圆圈,那么这不是这样做的方法。但是,如果它们是,这仍然有效。
  • 嗯,这是我尝试的第一件事,但是当两个物体发生碰撞时,它让我很难处理,因为我的玩家和敌人可以平移和旋转。
  • 这就是为什么你使用Rectangle.reshape(x,y,width,height) 为它创建一个名为udpdatePlayer(int x, int y) 或类似的方法,并让它更新玩家的矩形位置。但是,由于这些是圆圈,请参阅 ControlAltDel 的答案,因为它更适合这种情况。
【解决方案4】:

实际上,在 java 上对游戏中的碰撞建模的最佳方法是绘制 4 个命中框: 一个非常薄的矩形,位于角色的顶部、底部、左侧、右侧。 然后,如果敌人的一个命中框包含玩家的一个命中框(使用 intersects 方法),您将知道发生了碰撞,甚至更好的是,您将知道碰撞的一侧。

更多信息: https://www.youtube.com/watch?v=mdJNtXP1QiY

【讨论】:

  • 在角色周围画 4 个盒子不会和 1 个包含玩家的大盒子一样有效吗?
  • 一点也不!!如果有一个 hit box,我们假设左上角与敌人的一个 hit box 相交,碰撞是在顶部还是左侧?这就是为什么最好将它们分开。 youtube.com/watch?v=mdJNtXP1QiY
  • 但是按照这个逻辑,我可以说存储每个像素的每个点是最好的方法,即使最终玩家立即死亡,至少我们会确切地知道交叉点在哪里是...虽然我知道你要去哪里,只是在这种情况下它并不那么重要。
  • 但是如果玩家只有在碰撞发生在顶部、左侧、右侧时才会死亡怎么办。看看我发布的 youtube vi,你就会对它有所了解。不必担心每个像素。
  • 但是您很容易找到一种情况,您可以争辩说有必要担心每个像素。也许你想要一个完美的命中框。也许您希望死亡动画具有某种精确的基于方向的动画。即,如果一个人从 45 度以上被射中,而您想要一个完美角度的血液飞溅。您必须知道不会通过定向位置告诉您的入口点和出口点。
猜你喜欢
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 2023-03-21
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
相关资源
最近更新 更多