【问题标题】:Collision Detection Issues碰撞检测问题
【发布时间】:2017-05-30 11:42:35
【问题描述】:

我的游戏碰撞检测系统有点问题。 游戏中有几个相互连接的结构。但是,当它们之间存在另一个结构时,它们不应连接。

由于某些奇怪的原因,当在它们后面的直线上有一个结构时,它有时无法连接到直接相邻的结构。很少会产生其他奇怪的联系。

图片:

红色标记的节点应该是连接的。

代码:

public void drawConnections(Graphics g) {
    ArrayList<EnergyContainer> structurecopy = (ArrayList<EnergyContainer>) Mainclass.structures.clone(); //all structures in a list
    structurecopy.remove(this); //as we are member of the list
    structurecopy.removeIf(t -> (!hasStructureInRangeWithoutObstaclesInBetween(t))); 
    structurecopy.removeIf(t -> !t.receivesEnergyfromNeighbors()); //unimportant check if it is allowed to connect (its working)
    structurecopy.forEach(t -> drawConnectionTo(t, g)); //also works fine 
}

public boolean hasStructureInRangeWithoutObstaclesInBetween(Structure structureWhichShouldBeInRange) {
    // if in Range
    if (getRange() >= Math.hypot(structureWhichShouldBeInRange.getX() - getX(),
            structureWhichShouldBeInRange.getY() - getY())){ //checks if structure is in range
        ArrayList<EnergyContainer> structureclone = (ArrayList<EnergyContainer>) Mainclass.structures.clone();
        structureclone.remove(this); //again removes itself from the list
        structureclone.remove(structureWhichShouldBeInRange); //also removes target - so it doesn't block itself
        structureclone.removeIf(t -> !t.collidesWithLine(this.getX(), structureWhichShouldBeInRange.getX(),
                this.getY(), structureWhichShouldBeInRange.getY())); //removes it when it does not collide
        return structureclone.size() == 0; //returns true when no collisions are found
    }
    return false;
}

public boolean collidesWithLine(int x1, int x2, int y1, int y2) {
    // Line Segment - Circle Collision Detection
    double dx = x2 - x1;
    double dy = y2 - y1;
    double a = dx * dx + dy * dy; //this is the distance
    double b = 2 * dx * (x1 - getX()) + 2 * dy * (y1 - getY());
    double c = getX() * getX() + getY() * getY() + x1 * x1 + y1 * y1 - 2 * (getX() * x1 + getY() * y1)
            - getCollisionRadius() * getCollisionRadius();
    double discriminant = b * b - 4 * a * c;
    return discriminant >= 0; // no intersection -> discriminant <0

}

(我只为本文添加了 cmets,如果它们会导致编译错误,请忽略它们)。

谁能告诉我我做错了什么?

【问题讨论】:

  • 好吧,我真的需要至少一个提示...而且我不想造成重复...
  • 也许这有点宽泛。您能解释一下您使用的数学方法以及您认为问题可能出在哪里吗?
  • 我的建议是为collidesWithLine() 编写一个单元测试,以确定您是否放错了操作符。也很难看出计算实际做了什么,所以很容易混淆 '+' 和 '*' 例如。除此之外,您的 sn-p 还没有显示完整的图片。 collidesWithLine()范围内的this是什么? javadoc 注释也可以提供帮助。
  • 两点之间的距离:sqrt( (x2-x1)^2 + (y2-y1)^2),但您正在计算没有平方根的距离。这是我很容易发现的,代码中可能还有其他缺陷。

标签: java collision-detection collision


【解决方案1】:

这里可能有几个问题:

首先: 正如 Marat 所说:b 可能返回值 0。如果您的 getX()getY() 返回 x1y1,就会发生这种情况.如果是这种情况,您实际上是在这样做:(2dx * 0) + (2dy * 0)。如果是这种情况,它会对您以后的方程式产生负面影响。

其次:您很可能总是从您的最终方程式返回true

double discriminant = b * b - 4 * a * c;
//This breaks down to discriminant = b^2 * 4ac

即使此时b 为0,只要ac 的值大于0,return discriminant &gt;= 0; 就会为真;

我会强烈建议在我提到的两个部分放置一个断点,并在代码执行之前和之后检查你的值,这样你就可以看到数学发生了什么。

此外,Unity API 具有碰撞检测功能。你应该考虑一下。 https://docs.unity3d.com/Manual/PhysicsSection.html

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    假设: 1 如果我理解正确,这些是一些结构类的方法。 2 hasStructureInRangeWithoutObstaclesInBetween 是 collidesWithLine 的唯一调用者,或者至少问题是这样呈现的。

    因为 (2) b 总是 0。 我有一种感觉,这不是你的本意。请重新访问您的 collidesWithLine 方法。

    【讨论】:

    • 是同一类。结构描述了游戏中的“建筑”,因此是提供图片中显示的节点之一。 collidesWithLine 应该检查结构本身是否在线。因此,该结构有一个圆形的“命中框”,线条由参数给出。
    • 另一种方法实际上在两个结构之间画一条线,并检查每个其他结构是否在该线上。如果除了肯定在线的开始和结束对象之外的任何对象在线,它认为此连接被阻塞。
    • 你注意到b总是0了吗?
    • 除非getX()getY() 返回x1y1b 永远不会是0...不知道这些函数返回的一些值是什么,很难查明哪里出了问题
    • 致 Geoff:在这里给出的代码中,x1 始终是 GetX()。解释:对该函数的唯一调用在第 16 行。在此调用中,x1 = this.GetX() 和 y1 = this.GetY()。在第 28 行,我们计算 b。如果我们用传递的值替换 x1 和 y1,我们得到 b 总是 0。
    猜你喜欢
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多