【问题标题】:XNA 2D Platformer Collision and GravityXNA 2D 平台游戏碰撞和重力
【发布时间】:2013-07-16 15:48:49
【问题描述】:

我知道这个问题可能会被问到很多,对此我很抱歉。但是我的游戏中的碰撞问题已经有一段时间了,我需要一些帮助。

首先,该游戏是一款 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;
                            }

                        }

但问题是,如果玩家没有与矩形相交,我将重力设置为开启,因此他在与固体碰撞时会不断下落,然后放在顶部以不与它碰撞。我只需要知道:我怎样才能避免这种情况?有没有其他方法可以让玩家在不连续跌向固体的情况下打开重力,然后又回到固体顶部再次下落?

感谢任何帮助。

【问题讨论】:

  • 这个问题可能更适合我们的gamedev site。如果您希望我将此标记为迁移,请告诉我。

标签: xna collision gravity


【解决方案1】:

我解决这个问题的方法可能不是最佳的(事实上我确信它可能不是),但它在我所有的 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); 

sprite 类还需要一个布尔值来跟踪玩家是否应该跌倒。还有一个用于跟踪它是否可靠(显然,在初始化期间您可以根据需要分配)。

public bool isGrounded = false;
bool isSolid;

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

int gravityTotalI = 0;
int gravityCounterI = 0;

初始化我的精灵时,我通常将它们全部添加到一个列表中。这样我就可以做到这一点:

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.
}

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

希望这不是太啰嗦/不会遗漏任何重要的事情,我真的希望它有所帮助 - 我为与您完全相同的问题苦苦挣扎了很长时间,我知道这会多么令人沮丧!

我期待看到其他人处理此问题的技术!

【讨论】:

    猜你喜欢
    • 2011-07-06
    • 1970-01-01
    • 2015-05-20
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    相关资源
    最近更新 更多