首页 文章

XNA 2D平台碰撞和重力

提问于
浏览
0

我知道这个问题可能会被问到很多,为此我很抱歉 . 但我在游戏中遇到了一段时间的碰撞问题,我想要一些帮助 .

首先,游戏是2D平台游戏 . 每个固体都放在一个列表中 . 我有这个用于碰撞检测的代码,对我来说非常有用:

if (player.rectangle.Intersects(rect))
                        {
                            player1Collision = true;
                            colSolid = solid;
                            colRectangle = rect;
                        }


                        if (player1Collision)
                        {
                            Vector2 pos = player.position;
                            Vector2 pLeft = new Vector2(player.BoundingBox.Left, 0);
                            Vector2 pRight = new Vector2(player.BoundingBox.Right, 0);
                            Vector2 pTop = new Vector2(0, player.BoundingBox.Top);
                            Vector2 pBottom = new Vector2(0, player.BoundingBox.Bottom);

                            Vector2 sLeft = new Vector2(colSolid.BoundingBox.Left, 0);
                            Vector2 sRight = new Vector2(colSolid.BoundingBox.Right, 0);
                            Vector2 sTop = new Vector2(0, colSolid.BoundingBox.Top);
                            Vector2 sBottom = new Vector2(0, colSolid.BoundingBox.Bottom);

                            if (player.rectangle.Intersects(colRectangle))
                            {
                                if (player.velocity.X > 0 && Vector2.Distance(pRight, sLeft) < player.texture.Width / 2)//left
                                {
                                    player.velocity.X = 0f;
                                    pos.X = colSolid.BoundingBox.Left - player.BoundingBox.Width;

                                }
                                else if (player.velocity.X < 0 && Vector2.Distance(pLeft, sRight) < player.texture.Width / 2)//right
                                {
                                    player.velocity.X = 0f;
                                    pos.X = colSolid.BoundingBox.Right;
                                }

                                if (player.velocity.Y > 0 && Vector2.Distance(pBottom, sTop) < player.texture.Height/ 2) //top
                                {
                                    player.velocity.Y = 0f;
                                    player.gravityOn = false;                        
                                    pos.Y = colSolid.BoundingBox.Top - player.BoundingBox.Height;

                                }
                                else if (player.velocity.Y < 0 && Vector2.Distance(pTop, sBottom) < player.texture.Height / 2)//bottom
                                {
                                    player.velocity.Y = 0f;
                                    pos.Y = colSolid.BoundingBox.Bottom;

                                }
                                player.position = pos;
                            }
                            else
                            {
                                player.gravitySpeed = 0.15f;
                                player.gravityOn = true;
                            }

                        }

然而问题是如果玩家没有与矩形相交,我将重力设置为打开,因此当他与实体碰撞时他会连续下降,然后被放在上面以不与它发生碰撞 . 我需要知道的是:我怎么能避免这种情况?有没有其他方法可以让重力开启,而不会让玩家不断地向固体下降,只会被重新放回到固体顶部再次下降?

任何帮助表示赞赏 .

1 回答

  • 0

    我解决这个问题的方式可能不是最优的(实际上我确定它可能不是)但是到目前为止它在我所有的2D平台项目中都有用 .

    我首先为精灵类定义第二个矩形 . 此矩形将具有与主边界框相同的宽度和X坐标,但它会稍高(在我的情况下为2或3) . 您还需要偏移它,以便两个矩形的底边都是内联的,以说明:

    Rectangle boundingRect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
    Rectangle gravityRect = new Rectangle((int)boundingRect.X, (int)boundingRect.Y - 3, texture.Width, texture.Height + 3);
    

    精灵类还需要一个bool来跟踪玩家是否应该摔倒 . 一个是跟踪它是否是实体的(你明显在初始化期间根据需要分配) .

    public bool isGrounded = false;
    bool isSolid;
    

    在我的Game1类的顶部,我声明了2个整数:

    int gravityTotalI = 0;
    int gravityCounterI = 0;
    

    在初始化我的精灵时,我通常会将它们全部添加到List中 . 所以我可以这样做:

    foreach (Sprite s in spriteList)
    {
        if (s.isSolid)
        {
            gravityTotalI++;
        }
    }
    

    现在,我在Game1更新方法中使用这一点逻辑:

    foreach (Sprite s in spriteList)
    {
        if (!s.Equals(player)
        {
            if (player.boundingRect.Intersects(s.boundingRect) || player.boundingRect.Intersects(s.gravityRect))
            {
                player.isGrounded = true;
                gravityCounterI = 0;
            }
            else
            {
                gravCounterI++;
                if (gravCounterI >= gravTotalI)
                {
                     player.isGrounded = false;
                     gravCounterI = 0;
                }
            }
    
           if (player.boundingRect.Intersects(s.boundingRect))
            {
                player.position.Y -= 2f; //set the resistance of the platform here
            }
        }
    } //end of foreach loop.
    if (!player.isGrounded)
    {
        player.position.Y += 2f; //set the force of gravity here.
    }
    

    构建一个不错的定向碰撞引擎是另一回事,但这种技术将处理基础知识(并摆脱那种地狱般的反弹) .

    希望这不是太冗长/不会错过任何重要的事情,我真的希望它有所帮助 - 我很长一段时间都遇到了与你完全相同的问题,我知道它有多么令人沮丧!

    我期待着看到其他人处理这个问题的技巧!

相关问题