【问题标题】:XNA - 2D collision failure without any obvious patternXNA - 没有任何明显模式的 2D 碰撞失败
【发布时间】:2012-09-14 14:12:33
【问题描述】:

好的,所以我对 XNA 编程很陌生,我正在尝试编写一个平台游戏。我已经实现了像素完美碰撞,但它有时似乎无缘无故地失败(我无法弄清楚模式)并且英雄精灵穿过平台。

static bool IntersectsPixel(Rectangle rect1, Color[] data1, Rectangle rect2, Color[] data2)
    {
        int top = Math.Max (rect1.Top, rect2.Top);
        int bottom = Math.Min(rect1.Bottom, rect2.Bottom);
        int left = Math.Max (rect1.Left,rect2.Left);
        int right = Math.Min(rect1.Right,rect2.Right);


        //Top
        for(int y = top; y<bottom;y++)
            for (int x = left; x < right; x++)
            {
                Color color1 = data1[x-rect1.Left + (y-rect1.Top) * rect1.Width];

                Color color2 = data2[x - rect2.Left + (y - rect2.Top) * rect2.Width];

                if (color1.A != 0 && color2.A != 0)
                    return true;
            }



        return false;
    }

这是更新方法

     protected override void Update(GameTime gameTime)
    {

        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();


       foreach(Platform platform in platformList)
       {
           Rectangle check = new Rectangle(hero.GetRectangle().X - 300, hero.GetRectangle().Y - 300, 600, 600);
            if(check.Intersects(platform.rectangle))
           if (IntersectsPixel(hero.GetRectangle(), hero.textureData, platform.rectangle, platform.platformTextureData))
           {
               int direction = CheckDirection(platform,hero);
               if (hero.hasJumped == true && direction == 3 && hero.velocity.Y <= 0 )
                   {
                         hero.velocity.Y = 0f;
                         hero.SetPosition(new Vector2((float)hero.GetPosition().X, (float)platform.rectangle.Bottom));


                       break;
                   }
               else
               if (direction == 4 && hero.velocity.X >= 0)
               {
                   hero.velocity.X = 1;
                   hero.SetPosition(new Vector2((float)platform.rectangle.Left - (float)hero.GetRectangle().Width, (float)hero.GetPosition().Y));
                   break;
               }
               else
                   if (direction == 2 && hero.velocity.X <= 0)
                   {
                       hero.velocity.X = -1;

                       hero.SetPosition(new Vector2((float)platform.rectangle.Right - 1, (float)hero.GetPosition().Y));
                       break;
                   }
                   else

               if (direction == 1 && hero.velocity.Y >= 0)
               {
                   hero.velocity.Y = 0;
                   hero.hasJumped = false;
                   hero.SetPosition(new Vector2((float)hero.GetRectangle().X, (float)platform.rectangle.Y - (float)hero.GetRectangle().Height + 1));
                   hero.SetRectangle(new Rectangle((int)hero.GetPosition().X, (int)hero.GetPosition().Y, (int)hero.GetSize().X, (int)hero.GetSize().Y));
                   break;
               }




               }


           }


        hero.Update(gameTime);
        camera.Update(gameTime, hero, screenBounds);
        base.Update(gameTime);
    }

这是方向检查:

     private int CheckDirection(Platform platform,Hero hero)
    {
        int distance = Math.Abs(platform.rectangle.Top - hero.GetRectangle().Bottom);
        int direction = 1; //Top
        if (distance > Math.Abs(platform.rectangle.Right - hero.GetRectangle().Left))
        {
            distance = Math.Abs(platform.rectangle.Right - hero.GetRectangle().Left);
            direction = 2;
        }
        if (distance > Math.Abs(platform.rectangle.Bottom - hero.GetRectangle().Top))
        {
            distance = Math.Abs(platform.rectangle.Bottom - hero.GetRectangle().Top);
            direction = 3;
        }
        if (distance > Math.Abs(platform.rectangle.Left - hero.GetRectangle().Right))
        {
            direction = 4;
            distance = Math.Abs(platform.rectangle.Left - hero.GetRectangle().Right);
        }
        return direction;
    }

这些都是我与碰撞检测相关的所有功能。如果您碰巧对可能导致此问题的原因有任何想法,请告诉我。

非常感谢!

【问题讨论】:

    标签: c# xna collision


    【解决方案1】:

    我看到的一个可能的原因是,一开始你在两个对象周围构建了一个盒子:

        int top = Math.Max (rect1.Top, rect2.Top);
        int bottom = Math.Min(rect1.Bottom, rect2.Bottom);
        int left = Math.Max (rect1.Left,rect2.Left);
        int right = Math.Min(rect1.Right,rect2.Right);
    

    除非您翻转它,否则 XNA 的 Y 通常会在您向下(而不是向上)时变为正数。这意味着您实际上想要取底部的最大值和顶部的最小值,因为顶部总是小于底部。看起来你已经知道这一点了:

        for(int y = top; y<bottom;y++)
    

    我会继续寻找(没有实际项目很难测试)。我给你的另一个建议是做一些调试绘图。在交集函数认为像素接触或不接触的地方绘制。

    【讨论】:

    • 首先感谢您的回复。交换顶部和底部的 Max/Min 函数会很奇怪,因为这些线占据了交叉点的边界框。无论如何我都会尝试一下,因为我可能在纸上出错了。另外,我有点不确定我应该如何进行调试绘图,因为我不习惯使用 XNA,而且对编程也很陌生。再次感谢!
    【解决方案2】:

    由于延迟,你的角色每帧移动的距离可能超过了方块的高度,所以碰撞可能会认为它在方块之间,并导致它飞过。

    https://gamedev.stackexchange.com/questions/30458/platformer-starter-kit-collision-issues

    检查一下,它为我解决了问题。

    要么放慢移动速度,要么将位置变化限制为块的大小应该可以解决这个问题。

    【讨论】:

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