【问题标题】:Physics Engine (Collision Detection C#, GDI+)物理引擎(碰撞检测 C#、GDI+)
【发布时间】:2017-01-10 20:27:27
【问题描述】:

我目前正在使用 GDI+ 在 C# 中开发 2D 游戏引擎,并且已经到了想要添加简单碰撞检测的地步。

到目前为止,我可以使用以下代码检查我的玩家是否与另一个游戏对象相交:

public static bool IntersectGameObject(GameObject a, GameObject b)
{
    Rectangle rect1 = new Rectangle((int)a.Position.X, (int)a.Position.Y, a.Sprite.Bitmap.Width, a.Sprite.Bitmap.Height);
    Rectangle rect2 = new Rectangle((int)b.Position.X, (int)b.Position.Y, b.Sprite.Bitmap.Width, b.Sprite.Bitmap.Height);

    return rect1.IntersectsWith(rect2);
}

太棒了,我很高兴能走到这一步,但是我想知道我的玩家是否与游戏对象的顶部、底部、左侧或右侧相交,以便我可以停下来如果说我的玩家不会朝那个方向移动……他撞到了墙。我该怎么做呢?有人可以帮我吗:)

顺便说一句,游戏对象都有位图,都是 32 * 32 像素,所以我不需要每个像素的碰撞

提前谢谢你:)

【问题讨论】:

    标签: c# gdi+ physics game-physics


    【解决方案1】:

    计算两个矩形是否相交只是几个比较的问题(我知道你已经在使用IntersectsWith):

    if (Left > other.Right) return false;
    if (Right < other.Left) return false;
    if (Top > other.Bottom) return false;
    if (Bottom < other.Top) return false;
    return true;
    

    要确定碰撞的方向,您必须考虑以下可能性:

    • 一个矩形完全包含另一个(无方向碰撞)
    • 它可能会创建一个“加号”图形(向各个方向碰撞)
    • 矩形的一个角可能与另一个角的角相交(在两个方向上碰撞)

    不管怎样,判断左侧是否碰撞过:

    if (Right > other.Left && Right < other.Right && Left < other.Left)
    {
        // the right side of "this" rectangle is INSIDE the other
        // and the left side of "this" rectangle is to the left of it
    }
    

    最后但并非最不重要的一点是,如果您逐帧计算此对象,则一个对象可能会“跳过”另一个对象。对于更真实的物理,您必须跟踪时间并计算何时它会与矩形(每个边缘)相交。

    【讨论】:

    • 虽然我已将此标记为最佳答案,但我选择不走这条路。但是,您的回答非常有用。
    【解决方案2】:

    如果您需要碰撞检测,您需要一个刚体,您通常使用物理移动刚体。据我所见,上面的代码 sn-p 可能会出现问题。如果您使用变换移动移动它们,则应将它们标记为运动学。这意味着它不会被物理移动,而是被变换移动。

    您要移动的运动学刚体应在 FixedUpdate 期间完成以正确应用碰撞。

    如果你想知道你击中了哪一边,你可以将光线投射到物体上

    此代码 sn-p 给出了一个示例,显示了您可以在碰撞时执行的光线投射。最后,您使用的是哪个游戏引擎?

    //this ray will generate a vector which points from the center of 
     //the falling object TO object hit. You subtract where you want to go from where you are
    
     Ray MyRay = ObjectHit.position - ObjectFalling.position;
    
    
     //this will declare a variable which will store information about the object hit
     raycasthit MyRayHit; 
    
     //this is the actual raycast
     raycast(MyRay, out MyRayHit);
    
     //this will get the normal of the point hit, if you dont understand what a normal is 
     //wikipedia is your friend, its a simple idea, its a line which is tangent to a plane
    
     vector3 MyNormal = MyRayHit.normal;
    
     //this will convert that normal from being relative to global axis to relative to an
     //objects local axis
    
     MyNormal = MyRayHit.transform.transformdirection(MyNormal);
    
     //this next line will compare the normal hit to the normals of each plane to find the 
     //side hit
    
     if(MyNormal == MyRayHit.transform.up)
     {
     you hit the top plane, act accordingly
     }
     //important note the use of the '-' sign this inverts the direction, -up == down. Down doesn't exist as a stored direction, you invert up to get it. 
    
     if(MyNormal == -MyRayHit.transform.up)
     {
     you hit the bottom plane act accordingly
     }
     if(MyNormal == MyRayHit.transform.right)
     {
     hit right
     }
     //note the '-' sign converting right to left
     if(MyNormal == -MyRayHit.transform.right)
     {
     hit left
     }
    

    【讨论】:

    • 你一定没有看过我的整个帖子,我正在使用 GDI+ 在 c# 中编写自己的游戏引擎
    • 抱歉,我没把“我目前正在用 C# 开发 2D 游戏引擎”这句话理解为“我正在用 C# 开发 2D 游戏引擎”
    【解决方案3】:

    在你的玩家对象的一侧有 4 个不同的对象不是一个选项吗?根据哪一侧与游戏对象相交,你可以知道要阻止哪个运动方向?

    【讨论】:

      【解决方案4】:

      如果您逐帧处理,一个不错的选择可能是存储之前的位置P0x,P0y 和当前位置P1x,P1y

      然后,你可以计算一个向量 Vx,Vy 并且你可以计算交点Ix,Iy。这样您就可以获得更准确的碰撞信息。

      【讨论】:

        猜你喜欢
        • 2012-01-07
        • 2017-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多