尽管进行了多次检查,但碰撞代码无法正常工作

时间:2013-07-28 00:52:53

标签: c# xna collision

我正在研究XNA中的Collision。有些原因,尽管经过多次尝试,它仍无效。如果我触摸它,它会工作。但有时随机会停止运行,就像发生碰撞一样。它的工作方式是有50个20px乘20px的正方形。如果你的方块以任何方式触及另一个方格,那么游戏就结束了。

checkcollision()
    {
        for (int i = 0; i < 50; i++)
        {
            if ((loc.X + me.Width > enemyloc[i].X) && (loc.Y + me.Height > enemyloc[i].Y) && (loc.Y < enemyloc[i].Y) && (loc.X < enemyloc[i].X)) { return true; }
            if ((loc.X > enemyloc[i].X) && (enemyloc[i].X + enemy[i].Width > loc.X) && (loc.Y + me.Height > enemyloc[i].Y) && (loc.Y < enemyloc[i].Y)) { return true; }
            if ((loc.X > enemyloc[i].X) && (loc.X < enemyloc[i].X + enemy[i].Width) && (loc.Y > enemyloc[i].Y) && (loc.Y < enemyloc[i].Y + enemy[i].Height)) { return true; }
            if ((loc.X < enemyloc[i].X) && (loc.X + me.Width > enemyloc[i].X) && (loc.Y < enemyloc[i].Y) && (loc.Y < enemyloc[i].Y + enemy[i].Height)) { return true; }
        }
        return false;
    }

2 个答案:

答案 0 :(得分:2)

我同意这段代码看起来有点太复杂了。我建议将敌人和玩家碰撞盒存储为Rectangle struct的实例。 Rectangle结构提供了一个名为Contains的方法,定义为:

public bool Contains(int x, int y);

如果在x和y中定义的点存在于矩形中,则此方法将返回true。因此,使用此结构代码将变得更加简单:

public bool checkcollision(Rectangle player)
{
    for (int i = 0; i < enemy.Length; i++)
    {
        if (enemy[i].Contains(player.Left, player.Top)
            || enemy[i].Contains(player.Right, player.Top)
            || enemy[i].Contains(player.Left, player.Bottom)
            || enemy[i].Contains(player.Right, player.Bottom))
        {
            return true;
        }
    }
    return false;
}

答案 1 :(得分:0)

正如我在评论中所说, 太难读了。虽然我不会声称它是 问题(使用Mitch Wheat建议的调试器),但它确实可以解决!

首先,让我们概述单轴X的碰撞检测。我们不是先查看碰撞,而是查找 no collision 。当“(玩家离开敌人)或(玩家左边的敌人)”时,不会沿着X轴[仅]碰撞。 (如果这些都不是真的那么“敌人的玩家”必须是真的 - 如果需要的话使用图片。)

设p = Player,e = Enemy,然后当(p.X + p.W&lt; e.X)||时,无碰撞 [仅] (e.X + e.W&lt; p.X)。这意味着在相反/否定的情况下发生碰撞!

因此我们可以编写碰撞方法

bool Collides (IEntityBox p, IEntityBox e) {
    bool noCollisionX = (p.X + p.W < e.X) || (e.X + e.W < p.X);
    bool collisionX = !noCollisionX;
    bool noCollisionY = (p.Y + p.H < e.Y) || (e.Y + e.H < p.Y);
    bool collisionY = !noCollisionY;
    // not that the collision on BOTH axises must be fulfilled
    return collisionX && collisionY;
 }

备注(作为练习留下):

  1. IEntityBox具有X / Y和W / H属性,并且(0,0)被假定为屏幕的左上角。使用正确的类型/ propeties实现。如果玩家和其他实体之间的定位是统一的,那就更简单了。

  2. 可以重写表达式(并且可以应用De Morgan)来清理它。简单的折叠将消除所有变量,并使其“易于”阅读。

  3. 如果noCollisionX(暗示!collisionX)为真,我们不需要计算noCollisionY。如果折叠,可以使用if / else或短路评估。

  4. 同样清理用法:

    bool PlayerCollidesWithAnyEnemy () {
      foreach (var e in enemies) { // avoid hard-coding numbers
        if (Collides(player, e)) {
          return true;
        }
      }
      return false;
    }
    // ..
    var playerOopsed = PlayerCollidesWithAnyEnemy();
    

    或者,使用LINQ:

    var playerOopsed = enemies.Any(e => Collides(player, e));