跳跃与重力比较

5

我正在制作我的第一个XNA 2D游戏,但是遇到了一些问题。 如果我跳跃,我的角色会跳起来但却不会掉下来。 另外还有一个问题是,用户可以按住空格键跳得很高,我不知道如何阻止他这么做。这是我的代码:

跳跃部分:
    if (FaKeyboard.IsKeyDown(Keys.Space))
        {
            Jumping = true;
            xPosition -= new Vector2(0, 5);
        }

        if (xPosition.Y >= 10)
        {
            Jumping = false;
            Grounded = false;
        }

真正简单的基本引力:
    if (!Grounded && !Jumping)
        {
            xPosition += new Vector2(1, 3) * speed;
        }

这里是通过碰撞将接地设置为True或False的位置

    Rectangle MegamanRectangle = new Rectangle((int)xPosition.X, (int)xPosition.Y, FrameSizeDraw.X, FrameSizeDraw.Y);
        Rectangle Block1Rectangle = new Rectangle((int)0, (int)73, Block1.Width, Block1.Height);
        Rectangle Block2Rectangle = new Rectangle((int)500, (int)73, Block2.Width, Block2.Height);

        if ((MegamanRectangle.Intersects(Block1Rectangle) || (MegamanRectangle.Intersects(Block2Rectangle))))
        {
            Grounded = true;
        }
        else
        {
            Grounded = false;
        }

已测试并正常工作的是grounded bool(接地布尔)和gravity(重力)。有什么想法吗?提前感谢,如果需要代码的其他部分,请随时询问。
4个回答

5

处理跳跃的相对简单方法是将重力实现为矢量,将跳跃/移动实现为冲量。

例如:

foreach (Object obj in GameWorld)
{
    obj.Velocity *= 0.5; // Slow it down slightly
    obj.Velocity += GravityPerSecond * FrameTime; // Gravity adjusted for time
    obj.Move(obj.Velocity); // Handle collision and movement here
}

速度应该是一个与世界相同维度的向量,而Move方法则是将物体在给定向量方向上尽可能远地移动。

跳跃代码:

OnKeyDown(Key k)
{
    if (k == Key.Space)
    {
        obj.Velocity += Vector2(0, 10); // Add an upward impulse
    }
}

这将导致物体向上移动一段时间,然后开始下落。你可以使用类似的冲量来产生其他效果(移动、爆炸、碰撞)。当两个物体碰撞时,你需要让碰撞修改速度以实现弹跳。
这是一个非常简单的物理系统,将使未来的更改变得更加简单,并且可以允许一些有趣的关卡设计(改变重力等)。通过将跳跃从复杂的IsJumping代码抽象出来成为一个单一的机制,它简化了处理跳跃。
为了防止在不站在物体上时进行跳跃,你需要进行碰撞测试,或者追踪物体在向下方向上发生碰撞/停止碰撞的时间。也可能检查物体的垂直速度是否为零,只有在这种情况下才允许跳跃(可以避免在下落或向上移动时进行跳跃)。

我真的很喜欢这种方法!但是我是新手,不知道在“GameWorld”之外应该放什么。 - phadaphunk
1
无论你将游戏对象放在哪里,无论是世界还是场景管理器等,你可能希望保留物理对象的集合(仅限可移动对象,忽略静态层级)并使用它。 - ssube
1
+1;好建议。我的两分钱:根据你的游戏,有时更多的虚假物理可以给你更好的结果。就像马里奥游戏或几乎任何NES或SNES时代的平台游戏一样。在设计关卡时,您将拥有更简单的计算/较少的实验,并且解决某些问题(例如“隧道”或意外使您的物理在不同机器上工作方式不同)将不会那么困难。但它不会那么通用。如果您选择更通用的速度/加速度方法,就像这个答案建议的那样,您可能还需要研究终端速度建模。 - Merlyn Morgan-Graham

2
我相信这可能是答案:
更改你的
    if (FaKeyboard.IsKeyDown(Keys.Space))
    {
        Jumping = true;
        xPosition -= new Vector2(0, 5);
    }

    if (xPosition.Y >= 10)
    {
        Jumping = false;
        Grounded = false;
    }

to

    if (!Jumping && FaKeyboard.IsKeyDown(Keys.Space))
    {
        Jumping = true;
        Grounded = false;
    }

    if (Jumping)
    {
        xPosition -= new Vector2(0, 5);
    } 

    if (xPosition.Y >= 10)
    {
        Jumping = false;
    }

其他使用速度的答案确实是更好的方法,但这可能足以让您再次开始。


如果更符合你的重力模型,你也可以在解决方案的条件语句中使用 !Jumping 而不是 Grounded。 - Larry Smithmier
我尝试了,但它不起作用... 精灵根本不跳。 如果我将xPosition -= new Vector(0, 5)更改为new Vector(0, 20)或更高,则精灵会跳一点,但仍然不会下落。 :( 我卡住了 :( - phadaphunk

1

这里有一个非常简单的解决方案,可以让跳跃上下移动:

const float SCALE = 20.0f; //SPEED!!!
if (jump <= 15 && jump != 0)
            {
                humanPosition.Y -= SCALE * speed;
                jump++;
            }
            else if (jump > 15)
            {
                humanPosition.Y += SCALE * speed;
                jump++;
                if (jump == 32)
                {
                    jump = 0;
                    humanPosition.Y = 307;
                }
            }

并由...激活

            else if (keyboard.IsKeyDown(Keys.Up))
        {
            jump = 1;
            humanPosition.Y -= SCALE * speed;
        }

这个操作会通过将跳跃设置为1来启动跳跃。 如果你想限制角色只能在地面上跳跃,你可以添加类似于这样的条件。

if (humanPosition.Y != GROUNDLEVEL){}

0

跳跃不应该是一个布尔值,除非你需要它用于像动画或只能在跳跃时使用的技能之类的东西。

相反,你应该使用向量运动,当玩家接触地面并按下跳跃按钮时,将一个向上的跳跃向量添加到你的运动中。

然后,重力需要成为一个向下的向量,对抗着玩家,并自我处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接