XNA - 2D碰撞失败,没有任何明显的模式

时间:2012-09-22 09:40:38

标签: c# xna collision

好吧,所以我对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;
    }

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

非常感谢!

2 个答案:

答案 0 :(得分:0)

我看到的一件事可能是一个可能的原因,就是在开头围绕两个对象构建一个盒子:

    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会随着你的下降(而不是上升)而变得正面。这意味着你实际上想要获取最大底部和最小顶部,因为Top总是小于底部。看起来你已经知道了这条线的外观:

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

我会继续寻找(没有实际项目就很难测试)。我给你的另一个建议是做一些调试绘图。绘制交点函数认为像素正在触摸或未触摸的位置。

答案 1 :(得分:0)

由于滞后,你的角色移动的速度可能超过每帧的块高度,因此碰撞可能会认为它在块之间,并导致它飞过。

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

检查出来,它解决了我的问题。

要么减慢移动速度,要么将位置变化固定到块的大小,应该可以解决这个问题。