【问题标题】:Platformer tile collision problems平台游戏瓷砖碰撞问题
【发布时间】:2013-09-02 19:50:11
【问题描述】:

我正在开发一个平台游戏,我有一个 32x32 的精灵和 32x32 的图块。 我还使用了一个瓦片引擎,它在数组的帮助下生成地图。 我使用RectangleHelper.cs来修复与瓷砖和玩家的碰撞,到目前为止,它可以与瓷砖的顶部发生碰撞,也可以与瓷砖的左侧发生碰撞。

在图片一中,我展示了“On Top Of”碰撞效果很好。没有错误或任何东西。

在图 2 中,我展示了“Collision Left Of”,效果也很好。

但在图 3 中,您可以看到角色是浮动的。这是因为碰撞矩形以某种方式延伸了几个像素,这就是问题之一,我似乎无法找到任何答案。

在图 4 中,我尝试从拉伸的碰撞矩形的右侧进行碰撞,最后我跳回墙上大约 1 到 2 帧,所以我无法对其进行截图,但是这也是问题之一。

这是我的RectangleHelper.cs,它来自“oyyou9”在 youtube 上的瓷砖碰撞引擎教程,对他来说,一切都很好。

另外,如果我撞到块的底部,我的角色就​​会消失。

矩形助手.cs

public static class RectangleHelper
{

    public static bool TouchTopOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Bottom >= r2.Top - 1 &&
                r1.Bottom <= r2.Top + (r2.Height / 2) &&
                r1.Right >= r2.Left + (r2.Width / 5) &&
                r1.Left <= r2.Right - (r2.Width / 5));
    }

    public static bool TouchBottomOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Top <= r2.Bottom + (r2.Height / 5) &&
                r1.Top >= r2.Bottom - 1 &&
                r1.Right >= r2.Left + (r2.Width / 5) &&
                r1.Left <= r2.Right - (r2.Width / 5));
    }

    public static bool TouchLeftOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Right <= r2.Right &&
                r1.Right >= r2.Left  - 5&&
                r1.Top <= r2.Bottom - (r2.Width / 4) &&
                r1.Bottom >= r2.Top + (r2.Width / 4));  
    }

    public static bool TouchRightOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Left >= r2.Left &&
                r1.Left <= r2.Right &&
                r1.Top <= r2.Bottom - (r2.Width / 4) &&
                r1.Bottom >= r2.Top + (r2.Width / 4));
    }
}

正如你在这里看到的,有很多随机值,在视频中,他并没有真正说明它们有什么用,只是说我可能需要调整它以适应我的游戏。

以及我的播放器类中的碰撞方法:

public void Collision(Rectangle newRectangle, int xOffset, int yOffset)
    {
        if (rectangle.TouchTopOf(newRectangle))
        {
            rectangle.Y = newRectangle.Y - rectangle.Height;
            velocity.Y = 0f;
            hasJumped = false;
        }
        if (rectangle.TouchLeftOf(newRectangle))
        {
            position.X = newRectangle.X - rectangle.Width * 2;
        }
        if (rectangle.TouchRightOf(newRectangle))
        {
            position.X = newRectangle.X + newRectangle.Width +1;
        }
        if (rectangle.TouchBottomOf(newRectangle))
        {
            velocity.Y = 1f;
        }
    }

它使用RectangleHelper.cs 来修复碰撞。

【问题讨论】:

  • 避免在问题中复制所有代码,没有人会阅读它。
  • 哦,好吧,我只是认为几乎每个班级都有相互联系,但是,是的,我删除了一些。
  • 在这行代码中TouchLeftOf void,return (r1.Right &lt;= r2.Right &amp;&amp; r1.Right &gt;= r2.Left - 5 &amp;&amp; r1.Top &lt;= r2.Bottom - (r2.Width / 4) &amp;&amp; r1.Bottom &gt;= r2.Top + (r2.Width / 4));为什么在第二个条件中有-5?这不会导致你的角色在他真正进入瓷砖之前停下来吗?还有什么是加法/减法(+- (r2.Width / 4))在第 3 个和第 4 个条件下完成的?
  • 我不确定,正如我所说,我按照视频教程进行操作,他说我不必使用那些确切的数字,所以我尝试了不同的数字和组合,但得到了实际上没有差异..这与视频中他为运动所做的事情是否有关:velocity.X -= (float)gameTime.ElapsedGameTime.TotalMilliSeconds / 3;,但我使用我的移动位置变量,因为速度变量不起作用,仅适用于重力/下落部分:/我做了位置+=速度,但它没有产生任何差异:/有没有其他方法可以做到这一点?有任何想法吗??谢谢!
  • 这不是那个地方,您需要对其进行调试并将其缩小为一个没有大量代码的问题(或与此相关的项目)。虽然如果我不忙的话,我明天可能会发布我的碰撞代码。您发现的这段代码似乎有点奇怪,其中包含所有这些未知和随机值。此外,请确保您在运动计算中始终使用经过的时间。

标签: c# xna 2d collision-detection tile


【解决方案1】:

我不确定所有这些随机值在您的碰撞检查代码中做了什么,所以我认为这可能会解决您的问题:

    public static bool TouchTopOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Bottom >= r2.Top - 1 &&
                r1.Bottom <= r2.Top + (r2.Height / 2) &&
                r1.Right >= r2.Left &&
                r1.Left <= r2.Right);
    }

    public static bool TouchBottomOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Top <= r2.Bottom + (r2.Height / 2) &&
                r1.Top >= r2.Bottom - 1 &&
                r1.Right >= r2.Left  &&
                r1.Left <= r2.Right );
    }

    public static bool TouchLeftOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Right <= r2.Right &&
                r1.Right >= r2.Left &&
                r1.Top <= r2.Bottom &&
                r1.Bottom >= r2.Top);
    }

    public static bool TouchRightOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Left >= r2.Left &&
                r1.Left <= r2.Right &&
                r1.Top <= r2.Bottom &&
                r1.Bottom >= r2.Top);
    }

然后改变这个:

    if (rectangle.TouchLeftOf(newRectangle))
    {
        position.X = newRectangle.X - rectangle.Width * 2;
    }

到这里:

    if (rectangle.TouchLeftOf(newRectangle))
    {
        position.X = newRectangle.X - 1;
    }

HTH。它在很大程度上对我有用。希望这会消除您的一些主要错误,但我只想指出,您学习的最佳方法是自己调试。您可以开始的一种方法是按照图 3 中的方式设置所有内容,然后在您的 rectangle.TouchTopOf() 条件中放置一个断点,看看它是否返回 true,如果是,为什么它显然返回 true不应该。

【讨论】:

  • 我尝试使用它,但由于某种原因,我根本无法与任何东西发生碰撞,我的角色只会去地图上的一个随机位置:7 有没有人知道任何其他方法或什么瓷砖碰撞?
  • @UffePuffe,你真的应该自己写一个碰撞代码。如果您这样做,您将了解它是如何工作的,因此将能够轻松解决出现的任何问题。如果您要求其他人为您做,或者只是使用您甚至不理解的教程,您将永远不会学会如何自己编写它。而且我不认为 SO 是您来让其他人为您编写代码的地方。如果您遇到无法解决的问题并且无法理解您的大部分代码是如何工作的(并且没有复制和粘贴它),我相信人们会非常愿意提供帮助。写代码就是工作!
  • 而且你的角色不可能去“地图上的随机位置”(除非你使用随机生成器)。角色要去那个地方,因为那是代码告诉他去的地方......
【解决方案2】:
public static bool TouchLeftOf(this Rectangle r1, Rectangle r2)
{
    return (r1.Left <= r2.Right &&
            r1.Right >= r2.Right - 5 &&
            r1.Top <= r2.Bottom - (r2.Width / 4) &&
            r1.Bottom >= r2.Top + (r2.Width / 4));
}

【讨论】:

    【解决方案3】:
    public static bool TouchRightOf(this Rectangle r1, Rectangle r2)
    {
        return (r1.Right >= r2.Left &&
                r1.Left <= r2.Left - 5 &&
                r1.Top <= r2.Bottom - (r2.Width / 4) &&
                r1.Bottom >= r2.Top + (r2.Width / 4));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-11
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多