物理引擎(碰撞检测 C#、GDI+)
Physics Engine (Collision Detection C#, GDI+)
我目前正在使用 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 像素,所以我不需要每像素碰撞
提前谢谢你:)
如果你需要碰撞检测你需要一个刚体,你通常用物理移动刚体。据我所知,上面的代码片段可能存在问题。如果你用 transform move 移动它们,你应该标记为运动学的。这意味着它不会被物理移动,而是被变换移动。
要移动的运动学刚体应该在 FixedUpdate 期间完成以正确应用碰撞。
如果您想知道您击中了哪一侧,您可以对物体进行光线投射
此代码片段提供了一个示例,其中显示了您可以在碰撞时执行的光线投射。最后,您一直在使用哪个游戏引擎?
//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
}
在你的玩家对象的一侧有 4 个不同的对象不是一个选项吗,这样根据哪一侧与游戏对象相交你可以知道要防止哪个移动方向?
计算两个矩形是否相交只是一些比较的问题(我知道你已经在使用 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;
要确定碰撞的方向,您必须考虑以下可能性:
- 一个矩形完全包含另一个(无方向碰撞)
- 它可能会创建一个 "plus" 图形(在各个方向碰撞)
- 矩形的一个角可以与另一个角的角相交(在两个方向上碰撞)
总之,判断是否撞到左侧:
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
}
最后但同样重要的是,如果您逐帧计算此对象,则一个对象可能 "jump over" 另一个对象。对于更真实的物理学,您必须跟踪时间并计算 何时 它将与矩形(的每个边缘)相交。
如果您逐帧处理,一个不错的选择可能是存储之前的位置 P0x,P0y
和当前位置 P1x,P1y
。
然后,你可以计算一个向量Vx,Vy,你可以计算交点Ix,Iy
。这样您就可以获得更准确的碰撞信息。
我目前正在使用 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 像素,所以我不需要每像素碰撞
提前谢谢你:)
如果你需要碰撞检测你需要一个刚体,你通常用物理移动刚体。据我所知,上面的代码片段可能存在问题。如果你用 transform move 移动它们,你应该标记为运动学的。这意味着它不会被物理移动,而是被变换移动。
要移动的运动学刚体应该在 FixedUpdate 期间完成以正确应用碰撞。
如果您想知道您击中了哪一侧,您可以对物体进行光线投射
此代码片段提供了一个示例,其中显示了您可以在碰撞时执行的光线投射。最后,您一直在使用哪个游戏引擎?
//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
}
在你的玩家对象的一侧有 4 个不同的对象不是一个选项吗,这样根据哪一侧与游戏对象相交你可以知道要防止哪个移动方向?
计算两个矩形是否相交只是一些比较的问题(我知道你已经在使用 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;
要确定碰撞的方向,您必须考虑以下可能性:
- 一个矩形完全包含另一个(无方向碰撞)
- 它可能会创建一个 "plus" 图形(在各个方向碰撞)
- 矩形的一个角可以与另一个角的角相交(在两个方向上碰撞)
总之,判断是否撞到左侧:
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
}
最后但同样重要的是,如果您逐帧计算此对象,则一个对象可能 "jump over" 另一个对象。对于更真实的物理学,您必须跟踪时间并计算 何时 它将与矩形(的每个边缘)相交。
如果您逐帧处理,一个不错的选择可能是存储之前的位置 P0x,P0y
和当前位置 P1x,P1y
。
然后,你可以计算一个向量Vx,Vy,你可以计算交点Ix,Iy
。这样您就可以获得更准确的碰撞信息。