游戏编程:消除运动滞后(跳跃)

发布于 2024-12-20 21:09:53 字数 1275 浏览 1 评论 0原文

我正在开发一个类似 HTML5 3D fps 的引擎,它看起来已经相当不错了,但由于这可能是制作 3D 的最糟糕的语言选择之一,因此有时会出现明显的延迟。

我将运动 (WASD) 编程为独立于渲染速度,因此有时它非常不稳定,但其他时候则以可接受的 30+ fps 运行(当然取决于 CPU)。

我唯一无法集中注意力的是跳跃:目前跳跃是通过向下落变量添加一个正常量(重力始终为负,然后通过碰撞检测进行校正)然后减去一个常量来完成的,这称为每个当渲染新帧时,问题是当 fps 变低时,我感觉就像在月球上一样。与慢动作效果相比,我更喜欢生涩效果。

如果我使用与移动相同的方法(计算当前帧和最后一帧之间的时间),则扣除的变量有时会变得太大,并且跳跃顶点会发生变化(与高 fps 相比,变为该值的一半) - 这是不可接受的,因为跳跃高度必须始终相同。

下面是一些伪代码,可帮助理解问题(在一个渲染例程期间调用):

// when clicked on spacebar:
if(spacebar)
{
    // this defines jumping apex
    jump = 0.5
}

// constant added to y (vertical position) later in the code
cy += jump;

// terminal velocity = -2
if(jump > -2)
{
    // gravity (apex multiple to get maximum height)
    jump -= 0.05;
}

if(collision_with_floor)
{
    // stop falling
    cy = 0;

    if(jump < 0)
    {
        jump = 0;
    }
}

player.position.y += cy;

现在具有时间相关的跳跃(替换上面的代码):

// terminal velocity = -2
if(jump > -2)
{
    // gravity, 0.4 is an arbitrary constant
    jump -= (now - last_frame)*0.4;
    last_frame = now;
}

为了更好地说明,这里有一张正在发生的情况的图像:

在此处输入图像描述

蓝点表示帧渲染。

我什至不确定这是否是编写跳跃程序的正确方法。基本上,急躁和恒定的跳跃高度比平滑和慢动作效果更好。

I'm developing an HTML5 3D fps-like engine that already looks quite nice, but as this might be one of the worst language choices to make 3D there's noticeable lag sometimes.

I programmed movements (WASD) to be independent of rendering speed, so sometimes it's quite jerky, but other times is working at an acceptable 30+ fps (depending on CPU of course).

The only thing I can't wrap my mind around is jumping: currently the jumping is done by adding a positive constant to the falling variable (gravity is always negative and then corrected by collision detection) and then subtracting a constant, this is called every time a new frame is rendered, the thing is that when fps go low I feel like I'm on the moon. I prefer jerkiness to slow-mo effect.

If I use the same method like I do for moving (calculate time between current and last frame) the deducted variable gets too big sometimes and the jumping apex changes (to half of the value compared to high fps) - this is unacceptable as jumping height must be always the same.

Here's some pseudo-code to help understanding the problem (called during one rendering routine):

// when clicked on spacebar:
if(spacebar)
{
    // this defines jumping apex
    jump = 0.5
}

// constant added to y (vertical position) later in the code
cy += jump;

// terminal velocity = -2
if(jump > -2)
{
    // gravity (apex multiple to get maximum height)
    jump -= 0.05;
}

if(collision_with_floor)
{
    // stop falling
    cy = 0;

    if(jump < 0)
    {
        jump = 0;
    }
}

player.position.y += cy;

Now with time dependent jumping (replace in the code above):

// terminal velocity = -2
if(jump > -2)
{
    // gravity, 0.4 is an arbitrary constant
    jump -= (now - last_frame)*0.4;
    last_frame = now;
}

To illustrate even better here's an image of what's going on:

enter image description here

Blue dots indicate frame renders.

I'm not even sure of this is the right way to program jumping routine. Basically jerkiness and constant jumping height is better than smoothness and slow-mo effect.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清泪尽 2024-12-27 21:09:53

如果帧更新太慢而无法获得准确的物理效果,那么也许您可以修改跳跃顶点,以便玩家始终击中它。这里的提示可能是当 y 速度从正变为负时。如果我正确地阅读了您的伪代码,那么它看起来像:

old_cy = cy;
cy += jump;
if(old_cy > 0 && cy <= 0)
  player.position.y = jump_apex_height;

就您的图表而言,其想法是您想要识别到达橙色线的蓝点,然后将其提升到虚线。

现在我正在考虑这个问题,如果玩家确实每次都必须达到跳跃顶点,那么这甚至对于高速率更新也可能有所帮助。

If the frame updates are coming too slowly to get accurate physics, then maybe you can hack in the jump apex so that the player always hits it. The cue here might be when the y velocity changes from positive to negative. If I'm reading your pseudocode right, then it looks like:

old_cy = cy;
cy += jump;
if(old_cy > 0 && cy <= 0)
  player.position.y = jump_apex_height;

In terms of your graph, the idea is that you want to identify the blue dot that reaches the orange line, then bump it up to the dotted line.

And now that I'm thinking about it, if the player really has to reach the jump apex every time, then this might help even for high-rate updates.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文