【问题标题】:XNA/Monogame: Platformer Jumping Physics and Collider IssueXNA/Monogame:平台跳跃物理和对撞机问题
【发布时间】:2017-03-26 04:06:09
【问题描述】:

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

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

其中_position_direction_velocityVector2s。

我有一个简单的碰撞器 (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 贴在对撞机的一侧。

我想知道的是:

如何使用_position_direction_velocity 正确实现重力和跳跃?如何正确处理水平和垂直碰撞?

【问题讨论】:

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


【解决方案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...

代码背后的原理可以用一张图来解释:

在那张图片中,widthheight 对应于路口,紫色。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多