XNA / Monogame:Platformer跳跃物理和碰撞问题

时间:2017-03-26 04:06:09

标签: c# xna 2d game-physics monogame

我有一个精灵,Player。我通过以下方式更新Player的位置:

_position += (_direction * _velocity) * (float)gameTime.ElapsedGameTime.TotalSeconds;

_position_direction_velocityVector2的位置。

我有一个简单的对撞机(BoxCollider),它根据对撞机的位置和尺寸生成一个矩形(BoundingBox)。

Initialize()中,我创建了一个新的List<BoxCollider>,并用该级别的碰撞器填充它。

Update()上,我将列表传递给Player以检查是否存在冲突。

碰撞检查方法:

public void CheckPlatformCollision(List<BoxCollider> colliders, GameTime gameTime)
{
    var nextPosition = _position + (_direction * _velocity) * (float)gameTime.ElapsedGameTime.TotalSeconds;
    Rectangle playerCollider = new Rectangle((int)nextPosition.X, (int)nextPosition.Y, BoundingBox.Width, BoundingBox.Height);
    foreach(BoxCollider collider in colliders)
    {
        if(playerCollider.Intersects(collider.BoundingBox))
        {
            nextPosition = _position;
        }
    }
    Position = nextPosition;
}

现在,我尝试实施重力的每一种方式都失败了。如果Player从过高的位置掉落,nextPosition会离Player太远而使其停留在半空中。

我也遇到水平碰撞问题,问题类似:Player过早停止,两者之间留有空格。有时候我Player会碰到对手的一侧。

我想知道的是:

如何正确实施重力&amp;与_position_direction_velocity一起跳跃?如何正确处理水平和垂直碰撞?

1 个答案:

答案 0 :(得分:1)

对于重力,请在更新_position之前添加此内容:

_velocity += gravity * (float)gameTime.ElapsedGameTime.TotalSeconds;

其中gravity类似于new Vector2(0, 10)

对于跳跃,你需要在玩家按下跳跃按钮时设置速度的垂直分量:

if (jumpPressed && jumpAvailable)
{
    _velocity.Y = -10; // Numbers are example. You need to adjust this
    jumpAvailable = false;
}

当玩家触地时你需要重置jumpAvailable

碰撞是一件非常复杂的事情。但是如果你在互联网上寻找“XNA工具冲突”,你会发现很多答案。

有很多方法。其中一个是将玩家推回到boxcollider的边界,而不是像你在代码中那样让他移动。代码是:

if (IntersectsFromTop(playerCollider, collider.BoundingBox))
{
    _position.Y = collider.BoundingBox.Y - BoundingBox.Height;
}
else if (IntersectsFromRight(playerCollider, collider.BoundingBox))
{
    _position.X = collider.BoundingBox.X + collider.BoundingBox.Width;
}
// And so on...

辅助方法可以实现如下:

private static bool IntersectsFromTop(Rectange player, Rectangle target)
{
    var intersection = Rectangle.Intersect(player, target);
    return player.Intersects(target) && intersection.Y == target.Y && intersection.Width >= intersection.Height;
}

private static bool IntersectsFromRight(Rectange player, Rectangle target)
{
    var intersection = Rectangle.Intersect(player, target);
    return player.Intersects(target) && intersection.X + intersection.Width == target.X + target.Width && intersection.Width <= intersection.Height;
}
// And so on...

该代码背后的基本原理可用图片解释:

Top collision and left collision

在该图片中,widthheight对应于交叉点,为紫色。