2D游戏中跳跃的数学原理

8

我正在J2ME上工作,我的游戏循环做以下事情:

public void run() {
        Graphics g = this.getGraphics();
        while (running) {
            long diff = System.currentTimeMillis() - lastLoop;
            lastLoop = System.currentTimeMillis();
            input();
            this.level.doLogic();
            render(g, diff);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                stop(e);
            }
        }
    }

这只是一个基本的游戏循环,doLogic() 函数调用场景中所有角色的逻辑函数,render(g, diff) 调用场景中每个角色的 animateChar 函数。接下来,在 Character 类中的 animChar 函数将屏幕设置为如下:

protected void animChar(long diff) {
        this.checkGravity();
        this.move((int) ((diff * this.dx) / 1000), (int) ((diff * this.dy) / 1000));
        if (this.acumFrame > this.framerate) {
            this.nextFrame();
            this.acumFrame = 0;
        } else {
            this.acumFrame += diff;
        }
    }

这确保了所有的事情都必须按照机器从一个周期到另一个周期所需的时间来进行(请记住这是一台手机,而不是游戏电脑)。我相信这不是实现此行为的最有效方法,因此我完全接受在评论中对我的编程技能提出批评,但这是我的问题:当我让角色跳跃时,我所做的就是将他的dy设置为负值,例如-200,并将布尔值jumping设置为true,这会使角色向上移动,然后我有这个名为checkGravity()的函数,它确保所有上升的东西都必须下降,checkGravity还检查角色是否在平台上,所以我会简化它,以节省您的时间:
public void checkGravity() {
        if (this.jumping) {
            this.jumpSpeed += 10;
            if (this.jumpSpeed > 0) {
                this.jumping = false;
                this.falling = true;
            }
            this.dy = this.jumpSpeed;
        }
        if (this.falling) {
            this.jumpSpeed += 10;
            if (this.jumpSpeed > 200) this.jumpSpeed = 200;
            this.dy = this.jumpSpeed;
            if (this.collidesWithPlatform()) {
                this.falling = false;
                this.standing = true;
                this.jumping = false;
                this.jumpSpeed = 0;
                this.dy = this.jumpSpeed;
            }
        }
    }

问题在于,这个函数会更新dy,无论diff如何,导致在慢速机器上角色像超人一样飞行,而我不知道如何实现diff因素,使得当角色跳跃时,他的速度按比例随着游戏速度减少。有人能帮我解决这个问题吗?或者给我指点如何以正确的方式在J2ME中进行2D跳跃。


这是一个很长的问题。你可能想要提取出其精华。 - Aiden Bell
作为一个旁注 - 你真的想在J2ME游戏中做100个ticks/秒吗?正如某人所提到的,你应该真正地睡眠到下一个期望的唤醒点,而不是每次固定持续时间。 - Neil Coffey
4个回答

5

你是否应该根据经过的时间调整jumpSpeed?也就是说,速度可能会以-75 /秒的速度变化,因此您的diff应该是应用于jumpSpeed变化量的权重。

所以将diff传递给checkGrav并执行以下操作... jumpSpeed +=(diff *(rate_per_second))/ 1000;

(假设diff以毫秒为单位)

(理想情况下,这将使它就像真正的重力:D)


这完全解决了问题,我进行了单元测试,所有手机都跳到了类似的高度!天啊,我真的需要再读一遍那些物理书,谢谢Gregd!! - fixmycode

3

为什么不直接通过diff来缩放所有常量?

顺便说一下,我曾经参与过一个商业游戏的开发,在这个游戏中,角色向下时的重力是向上时的两倍。不知道为什么,人们更喜欢这样。


我的点赞是基于你并非凭空捏造这个内容。 - Tom Hawtin - tackline
哈哈。你的怀疑态度令人钦佩。游戏名为“Bouncers”,是为SegaCD设计的。该游戏基于我为Commodore 64编写的《Basketball Sam&Ed》(COMPUTE!的Gazette游戏)。 - Nosredna
1
在我开发的时候,我会和朋友一起测试以获取他们的反馈。我们总是提到SNES马里奥系列,其中马里奥下降时有较低的重力,给人一种“轻盈”的感觉。有趣的是,人们如何理想化物理学。 - fixmycode
1
哦,也许我搞错了。那是很久以前的事了。 :-) - Nosredna

0
这似乎更多是关于游戏设计问题,而不是跳跃的数学问题。在运行在不同处理器上的游戏中,一个游戏可能会执行得更快,而另一个游戏可能会执行得更慢(从而改变整个游戏的速度),这是一个常见的问题。我不确定游戏中的常见做法是什么,但是每当我制作自己的2D游戏时(它们很有趣),我都会有一个游戏时钟的概念。在更快的机器上,

long diff = System.currentTimeMillis() - lastLoop;
lastLoop = System.currentTimeMillis();

将会更低。等待时间将从差异中派生,以便游戏在大多数机器上以相同的速度运行。我还会将渲染方法放在单独的线程中,以便游戏速度不受图形的影响。


你能详细说明一下如何使等待时间与差异相关吗? - fixmycode

0

我可以给出这样的公式(我在任何地方都使用它)。X是参数,从零开始到跳跃长度结束。 如果你想让某人跳到某个高度(H)和某个长度(L),那么跳跃的函数将如下所示(它永远不会有所不同):

y = 负号( (x - 跳跃长度除以2) 的平方乘以4再乘以跳跃高度,再除以跳跃长度的平方,最后加上跳跃高度。

y = -(x-l/2)(x-l/2)*4*h/(l*l) + h

如果你希望跳跃物体着陆在某个东西上,那么你可以检查每一个新的X是否大致站在一个平台上,如果它站在某个东西上,那么不要让它停下来,而是让它的Y位置与平台的Y位置完全相等。

如果你正在使用类似Flash或其他具有反向y轴的基础,则将函数输出乘以-1;


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