Math N游戏教程碰撞检测凸/凹

Math N游戏教程碰撞检测凸/凹,math,collision-detection,physics,game-physics,Math,Collision Detection,Physics,Game Physics,我遵循N game教程来处理我的一个游戏的碰撞检测,这个方法中有一点不清楚,那就是他们在这一页上讨论了分离轴定理,但是如果你在实现(教程A)中看到没有我可以看到分离轴被处理的地方。在下面的URL中,部分-->=圆形=-->讨论了如何处理AABB与凸面/凹面形状之间的碰撞。 我有向量和独立轴实现的基本概念,但不是这种方法,我从本教程中了解到的是整个N游戏世界由5-8个不同的形状(瓷砖)组成,每个瓷砖依次水平/垂直旋转,形成4个面向左、右、上、下的组合。这些面信息存储在每个磁贴中,即signx,y

我遵循N game教程来处理我的一个游戏的碰撞检测,这个方法中有一点不清楚,那就是他们在这一页上讨论了分离轴定理,但是如果你在实现(教程A)中看到没有我可以看到分离轴被处理的地方。在下面的URL中,部分
-->=圆形=-->
讨论了如何处理AABB与凸面/凹面形状之间的碰撞。

我有向量和独立轴实现的基本概念,但不是这种方法,我从本教程中了解到的是整个N游戏世界由5-8个不同的形状(瓷砖)组成,每个瓷砖依次水平/垂直旋转,形成4个面向左、右、上、下的组合。这些面信息存储在每个磁贴中,即signx,y

obj-是播放器(矩形) t形瓦 x、 y-包围盒投影

实现:有人能解释一下这段代码到底在做什么吗?

function ProjAABB_Concave(x,y,obj,t)
{       
    //if distance from "innermost" corner of AABB is further than tile radius,
    //collision is occuring and we need to project

    var signx = t.signx;
    var signy = t.signy;

    var ox = (t.pos.x + (signx*t.xw)) - (obj.pos.x - (signx*obj.xw));//(ox,oy) is the vector form the innermost AABB corner to the
    var oy = (t.pos.y + (signy*t.yw))- (obj.pos.y - (signy*obj.yw));//circle's center

    var twid = t.xw*2;
    var rad = Math.sqrt(twid*twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
                                        //note that this should be precomputed at compile-time since it's constant

    var len = Math.sqrt(ox*ox + oy*oy);
    var pen = len - rad;
    if(0 < pen)
    {
        //collision; we need to either project along the axes, or project along corner->circlecenter vector

        var lenP = Math.sqrt(x*x + y*y);
        if(lenP < pen)
        {
            //it's shorter to move along axis directions
            obj.ReportCollisionVsWorld(x,y,x/lenP, y/lenP, t);

            return COL_AXIS;
        }
        else
        {
            //project along corner->circle vector
            ox /= len;//len should never be 0, since if it IS 0, rad should be > than len
            oy /= len;//and we should never reach here

            obj.ReportCollisionVsWorld(ox*pen, oy*pen, ox, oy, t);

            return COL_OTHER;
        }

    }

    return COL_NONE;

}
功能项目(x、y、obj、t)
{       
//如果距AABB“最内侧”角的距离大于瓷砖半径,
//冲突正在发生,我们需要预测
var signx=t.signx;
var-signy=t.signy;
var ox=(t.pos.x+(signx*t.xw))-(obj.pos.x-(signx*obj.xw));/(ox,oy)是从最内侧的AABB角到
var oy=(t.pos.y+(signy*t.yw))-(obj.pos.y-(signy*obj.yw));//圆的中心
var twid=t.xw*2;
var rad=Math.sqrt(twid*twid+0);//这为我们提供了以瓷砖的角为中心并延伸到瓷砖的对边的圆的半径;
//请注意,这应该在编译时预计算,因为它是常量
var len=数学sqrt(ox*ox+oy*oy);
var pen=len-rad;
如果(0<笔)
{
//碰撞;我们需要沿轴投影,或沿角->圆心向量投影
var lenP=Math.sqrt(x*x+y*y);
if(lenP圆向量投影
ox/=len;//len永远不应该是0,因为如果它是0,rad应该大于len
oy/=len;//我们永远也到不了这里
对象报告冲突VSWorld(ox*pen,oy*pen,ox,oy,t);
返回其他列;
}
}
返回colu_NONE;
}

我认为最好是显示底层物理算法,然后你可以更快地理解代码

我认为最好是显示底层物理算法,然后你可以更快地理解代码

这是一个简单的球体与球体碰撞。看到他们做的部分了吗

var pen = len - rad;
if(0 < pen)
var ox = (t.pos.x + (signx*t.xw)) - (obj.pos.x - (signx*obj.xw));//(ox,oy) is the vector form the innermost AABB corner to the
var oy = (t.pos.y + (signy*t.yw))- (obj.pos.y - (signy*obj.yw));//circle's center

他们正在将“t”对象移动到“obj”参照系。

这是一个简单的球体与球体碰撞。看到他们做的部分了吗

var pen = len - rad;
if(0 < pen)
var ox = (t.pos.x + (signx*t.xw)) - (obj.pos.x - (signx*obj.xw));//(ox,oy) is the vector form the innermost AABB corner to the
var oy = (t.pos.y + (signy*t.yw))- (obj.pos.y - (signy*obj.yw));//circle's center

他们正在将“t”对象移动到“obj”参照系。

显然,这是非常非常糟糕的碰撞代码。计算len和rad的Math.sqrt,然后计算lenP是非常愚蠢的:直接比较平方和。这是游戏碰撞检测101。真的。@SyntaxT3rr0r:我明白了,但如果你看到这个游戏的速度/平滑度非常快,这是因为这些预先计算好的数学,这就是为什么它吸引我阅读本教程的原因。但是,您能否建议任何关于处理AABB和凸面/凹面之间碰撞的教程。除了遵循本教程之外,我还实现了单独的基于轴的碰撞检测,但它仅适用于凸面形状,而不适用于圆形形状。显然,这是非常非常糟糕的碰撞代码。计算len和rad的Math.sqrt,然后计算lenP是非常愚蠢的:直接比较平方和。这是游戏碰撞检测101。真的。@SyntaxT3rr0r:我明白了,但如果你看到这个游戏的速度/平滑度非常快,这是因为这些预先计算好的数学,这就是为什么它吸引我阅读本教程的原因。但是,您是否可以建议任何关于处理AABB和凸面/凹面之间碰撞的教程。除了遵循本教程之外,我还实现了单独的基于轴的碰撞检测,但它仅适用于凸面形状,不适用于圆形形状。@SyntaxT3rr0r:这是一个教程,不需要指出它的缺陷(从长远来看,阿南德可能会发现他可以使用半径平方)。如果他们检查半径(两个物体中心之间的距离==两个物体的总半径),我的问题是如何使用这种方法来找到单面弯曲形状之间的碰撞“请参考-图6”。它们碰撞两个对象,就像它们是两个球体一样。矩形“球体”是假想的“球体”从中心到角部,如果两个球体相交,则检查矩形的角部和凹面半径之间的距离是否足够接近,以便碰撞。要排除凹面对象的角部,如果矩形的球体半径>len,则len-rad将小于0,且不会发生碰撞:)现在我理解了代码以及您的描述,现在我很想知道这个冲突代码有什么问题。还有一个问题是如何在曲面上执行碰撞检测(如Locoroco game worlk)?@Anandh:这段代码的缺点是:1)大量使用
Math.sqrt
,你可以使用所有的平方和瞧;2)signx*obj.xw可以对局部变量使用条件符号更改,比乘法更便宜。考虑到这些“坏东西”只有在你使用这些代码碰撞数千个物体或者你的代码将在移动平台上运行时才是坏的(计算能力消耗电池更快)。@SyntaxT3rr0r:这是一个教程,不需要指出它的陷阱(从长远来看,Anandh可能会发现他可以使用radiu)