防止动画游戏中的碰撞

时间:2018-01-14 20:17:16

标签: c# collision-detection collision

我一直试图设法防止我的角色碰到墙壁,所以他无法通过它,但我找不到一个正确的做法,就像你在这个视频中看到的那样(我录制的) 。对(合适的)麦克风质量感到抱歉:https://youtu.be/jhTSDgSXXa8。我还说防止碰撞,但它检测到并停止但你可以通过。

碰撞代码是:

foreach (PictureBox pbMur in pbListeMurs)
{
    if (pbCharacterCat.Bounds.IntersectsWith(pbMur.Bounds))
    {
        if (pbCharacterCat.Right > pbMur.Left)
        {
            bWalkRight = false;
            bIdle = true;              
        }                        
     } 
}

谢谢! :d

1 个答案:

答案 0 :(得分:1)

我不确定您是如何使用bIdlewalkRight的,但是这些类型的布尔标记很容易出错,它会将您的整个代码变成一个完整的混乱尝试堵塞孔并在此过程中弹出新的孔。

首先,你为什么甚至需要它们?这不够吗?

var newPotentialCharacterBounds = 
    GetNewBounds(pbCharacterCat.Bounds, movementDirection);
var collidedWalls = pbListeMurs.Where(wall => 
    wall.Bounds.IntersectsWith(newPotentialCharacterBounds));

if (!collidedWall.Any())
{
    pbCharacterCat.Bounds = newPotentialCharacterBounds   
}

//else do nothing

这是如何工作的?嗯,前提是你的角色不能从无效位置开始,如果永远不允许它到达无效位置,那么你永远不需要撤消动作或重置位置。

我建议您创建一个描述所有可能方向的枚举:

enum Direction { Up, Down, Left, Right };

当给出相应的方向命令时,获取角色的潜在新位置(newPotentialCharacterBoundsGetNewBounds)。如果那个位置与任何东西发生碰撞,那么就什么都不做,如果它没有移动!

更新:伪代码如下:

//event handler for move right fires, and calls:
TryMove(pbCharacterCat, Direction.Right)


//event handler for move left fires and calls:
TryMove(pbCharacterCat, Direction.Left)

//etc.

private static Rectangle GetNewBounds(
    Rectangle current, Direction direction)
{
     switch (direction)
     {
          case Direction.Right:
          {
              var newBounds = current;
              newBounds.Offset(horizontalDelta, 0);
              return newBounds;
          }
          case Direction.Left:
          {
              var newBounds = current;
              newBounds.Offset(-horizontalDelta, 0);
              return newBounds;
           }
          //etc.   
}

//uses System.Linq
private bool TryMove(Control ctrl, Direction direction)
{
    var newBounds = 
        GetNewBounds(ctrl.Bounds, direction);
    var collidedWalls = pbListeMurs.Where(wall => 
        wall.Bounds.IntersectsWith(newBounds));

    if (!collidedWall.Any())
    {
        ctrl.Bounds = newBounds;   
        return true;
    }

    //Can't move in that direction
    Debug.Assert(collidedWall.Single); //sanity check
    return false;
}

如果运动成功与否,则返回TryMove,现在您可以利用该信息;例如,不同的声音效果等。