Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 碰撞检测与矩形_C#_Collision Detection_Monogame_Rectangles - Fatal编程技术网

C# 碰撞检测与矩形

C# 碰撞检测与矩形,c#,collision-detection,monogame,rectangles,C#,Collision Detection,Monogame,Rectangles,当我的角色与另一个精灵碰撞时,我试图让它的速度为零。它可以做到这一点,但是当纹理发生碰撞时,纹理之间的距离会增加。如果我选择更高的“速度”值,则该值越高,发生碰撞时纹理之间的距离就越远 在1f的速度下,碰撞似乎可以正常工作(两种纹理都接触),但1f对于我的游戏来说太慢了,我不知道如何在不增加碰撞距离的情况下增加碰撞 我相信这是因为我在碰撞区域中使用了:rectangle.Right+Velocity.X,但我不确定如何修改它来解决我的问题。我们将不胜感激 //In Sprite class

当我的角色与另一个精灵碰撞时,我试图让它的速度为零。它可以做到这一点,但是当纹理发生碰撞时,纹理之间的距离会增加。如果我选择更高的“速度”值,则该值越高,发生碰撞时纹理之间的距离就越远

在1f的速度下,碰撞似乎可以正常工作(两种纹理都接触),但1f对于我的游戏来说太慢了,我不知道如何在不增加碰撞距离的情况下增加碰撞

我相信这是因为我在碰撞区域中使用了:rectangle.Right+Velocity.X,但我不确定如何修改它来解决我的问题。我们将不胜感激

//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;
      }
   }      
}