C# 碰撞检测与矩形
当我的角色与另一个精灵碰撞时,我试图让它的速度为零。它可以做到这一点,但是当纹理发生碰撞时,纹理之间的距离会增加。如果我选择更高的“速度”值,则该值越高,发生碰撞时纹理之间的距离就越远 在1f的速度下,碰撞似乎可以正常工作(两种纹理都接触),但1f对于我的游戏来说太慢了,我不知道如何在不增加碰撞距离的情况下增加碰撞 我相信这是因为我在碰撞区域中使用了:rectangle.Right+Velocity.X,但我不确定如何修改它来解决我的问题。我们将不胜感激C# 碰撞检测与矩形,c#,collision-detection,monogame,rectangles,C#,Collision Detection,Monogame,Rectangles,当我的角色与另一个精灵碰撞时,我试图让它的速度为零。它可以做到这一点,但是当纹理发生碰撞时,纹理之间的距离会增加。如果我选择更高的“速度”值,则该值越高,发生碰撞时纹理之间的距离就越远 在1f的速度下,碰撞似乎可以正常工作(两种纹理都接触),但1f对于我的游戏来说太慢了,我不知道如何在不增加碰撞距离的情况下增加碰撞 我相信这是因为我在碰撞区域中使用了:rectangle.Right+Velocity.X,但我不确定如何修改它来解决我的问题。我们将不胜感激 //In Sprite class
//In Sprite class
#region Collision
protected bool IsTouchingLeft(Sprite sprite)
{
return rectangle.Right + Velocity.X > sprite.rectangle.Left &&
rectangle.Left < sprite.rectangle.Left &&
rectangle.Bottom > sprite.rectangle.Top &&
rectangle.Top < sprite.rectangle.Bottom;
}
protected bool IsTouchingRight(Sprite sprite)
{
return rectangle.Left + Velocity.X < sprite.rectangle.Right &&
rectangle.Right > sprite.rectangle.Right &&
rectangle.Bottom > sprite.rectangle.Top &&
rectangle.Top < sprite.rectangle.Bottom;
}
protected bool IsTouchingTop(Sprite sprite)
{
return rectangle.Bottom + Velocity.Y > sprite.rectangle.Top &
rectangle.Top < sprite.rectangle.Top &&
rectangle.Right > sprite.rectangle.Left &&
rectangle.Left < sprite.rectangle.Right;
}
protected bool IsTouchingBottom(Sprite sprite)
{
return rectangle.Top + Velocity.Y < sprite.rectangle.Bottom &
rectangle.Bottom > sprite.rectangle.Bottom &&
rectangle.Right > sprite.rectangle.Left &&
rectangle.Left < sprite.rectangle.Right;
}
#endregion
//在Sprite类中
#区域碰撞
受保护的bool IsTouchingLeft(精灵精灵)
{
返回矩形.Right+Velocity.X>sprite.rectangle.Left&&
矩形.Leftsprite.rectangle.Top&&
矩形。顶部sprite.rectangle.Right&&
矩形.Bottom>sprite.rectangle.Top&&
矩形。顶部sprite.rectangle.Top&
矩形.Topsprite.rectangle.Left&&
矩形。左sprite.rectangle.Bottom&&
矩形.Right>sprite.rectangle.Left&&
矩形。左
//在MainChar类中
foreach(sprite中的变量sprite)
{
如果(精灵==此)
{
继续;
}
如果(Velocity.X>0&&IsTouchingLeft(精灵)| | Velocity.X<0&&IsTouchingRight(精灵))
{
速度X=0;
}
如果(Velocity.Y>0&&IsTouchingTop(精灵)| | Velocity.Y<0&&IsTouchingBottom(精灵))
{
速度Y=0;
}
if(精灵.矩形.相交(矩形))
{
hasDied=true;
}
}
正确处理多个碰撞需要分步执行,重复碰撞检查,直到不再发生碰撞或计数器过期。这就是物理引擎的工作原理
我将展示一种不同的方法。它要求不做导致碰撞的动作,并且每一步调整一半的速度。减速,直到达到最大log2(速度)
步数(速度<32,5步):
foreach(精灵中的变量精灵)
{
如果(精灵==此)
{
继续;
}
//将()用于混合和&&和| |是一种很好的做法
if((Velocity.X>0&&IsTouchingLeft(精灵))| |(Velocity.X<0&&IsTouchRight(精灵)))
{
速度X*=0.5f;
//通过减半,速度将指数衰减为0
}
if((Velocity.Y>0&&IsTouchingTop(sprite))| |(Velocity.Y<0&&IsTouchingBottom(sprite)))
{
速度Y*=0.5f;
}
if(精灵.矩形.相交(矩形))
{
hasDied=true;
}
//使用“新速度”更新位置。
}
您可能必须修复死亡情况,但不清楚何时触发。编写的代码将向上移动到另一个对象,但不会自己重叠
以下代码是我认为您想要的(以1的速度移动,直到重叠)
foreach(精灵中的变量精灵)
{
如果(精灵==此)
{
继续;
}
//将()用于混合和&&和| |是一种很好的做法
if((Velocity.X>0&&IsTouchingLeft(精灵))| |(Velocity.X<0&&IsTouchRight(精灵)))
{
如果(Velocity.X>=2)//将其限制在1以上的最小值
{
速度X*=0.5f;
//通过减半,速度将指数衰减为0
}
if(精灵.矩形.相交(矩形))
{
Velocity.X=0;//这里可能也需要对Y执行此操作。
hasDied=true;
}
}
if((Velocity.Y>0&&IsTouchingTop(sprite))| |(Velocity.Y<0&&IsTouchingBottom(sprite)))
{
如果(Velocity.Y>=2)//将其限制在1以上的最小值
{
速度Y*=0.5f;
//通过减半,速度将指数衰减为0
}
if(精灵.矩形.相交(矩形))
{
Velocity.Y=0;//这里可能也需要对X执行此操作。
hasDied=true;
}
}
}
我认为这是因为您的IsTouching*
方法确实应该命名为WillBeTouching*
,因为您正在向当前位置添加速度。我想到两件事。降低速度以使它们完全碰撞,或将碰撞位置设置为可能发生碰撞的位置。如果由于一个精灵与另一个精灵重叠而检测到碰撞,请将移动精灵的速度设置为0,但也要设置其位置,使其位于/靠着/接触(任意一侧)如果我降低速度,我的角色将移动得太慢,但是,如果我错了,请纠正我,我认为我无法将位置设置为它们碰撞的位置,因为我在不同的位置与多个精灵碰撞。
//In MainChar class
foreach (var sprite in sprites)
{
if (sprite == this)
{
continue;
}
if (Velocity.X > 0 && IsTouchingLeft(sprite) || Velocity.X < 0 && IsTouchingRight(sprite))
{
Velocity.X = 0;
}
if (Velocity.Y > 0 && IsTouchingTop(sprite) || Velocity.Y < 0 && IsTouchingBottom(sprite))
{
Velocity.Y = 0;
}
if (sprite.rectangle.Intersects(rectangle))
{
hasDied = true;
}
}
foreach (var sprite in sprites)
{
if (sprite == this)
{
continue;
}
// it is good practice to use () for mixed && and ||
if ((Velocity.X > 0 && IsTouchingLeft(sprite)) || (Velocity.X < 0 && IsTouchingRight(sprite)))
{
Velocity.X *= 0.5f;
// by halving, the velocity will exponentially decay to 0
}
if ((Velocity.Y > 0 && IsTouchingTop(sprite)) || (Velocity.Y < 0 && IsTouchingBottom(sprite)))
{
Velocity.Y *= 0.5f;
}
if (sprite.rectangle.Intersects(rectangle))
{
hasDied = true;
}
// use new velocity to update the position.
}
foreach (var sprite in sprites)
{
if (sprite == this)
{
continue;
}
// it is good practice to use () for mixed && and ||
if ((Velocity.X > 0 && IsTouchingLeft(sprite)) || (Velocity.X < 0 && IsTouchingRight(sprite)))
{
if (Velocity.X >= 2) // cap it at a minimum above 1
{
Velocity.X *= 0.5f;
// by halving, the velocity will exponentially decay to 0
}
if (sprite.rectangle.Intersects(rectangle))
{
Velocity.X = 0; // probably need to do this for Y here as well.
hasDied = true;
}
}
if ((Velocity.Y > 0 && IsTouchingTop(sprite)) || (Velocity.Y < 0 && IsTouchingBottom(sprite)))
{
if (Velocity.Y >= 2) // cap it at a minimum above 1
{
Velocity.Y *= 0.5f;
// by halving, the velocity will exponentially decay to 0
}
if (sprite.rectangle.Intersects(rectangle))
{
Velocity.Y = 0; // probably need to do this for X here as well.
hasDied = true;
}
}
}