【问题标题】:Implement hermite interpolation - multiplayer game实现 Hermite 插值 - 多人游戏
【发布时间】:2019-03-22 14:40:22
【问题描述】:

我正在尝试创建客户端-服务器架构。我被困在插值部分。现在,我有一个非常幼稚的插值算法实现。我让每个玩家都有一个位置历史记录,每当我从服务器收到其他玩家的位置数据时,我都会将该位置推送到该数组中。我使用最旧的位置历史记录以恒定速度插入到新位置的每个客户端框架。

// when new position for other player recieved 
p.stateHistory.push(data)

// Every client frame
if(p.stateHistory.length < 1)
            return false

    let deltaPosition = p.stateHistory[0].position.clone().sub(p.clientPosition)
    let direction = Math.atan2(deltaPosition.y, deltaPosition.x)
    let velocity = new Vector2(Math.cos(direction), Math.sin(direction)).scale(30/100)

    let threshold = 10
    if(deltaPosition.magnitude() < threshold) {
        p.clientPosition.x = p.stateHistory[0].position.x
        p.clientPosition.y = p.stateHistory[0].position.y
        p.stateHistory.shift()
    } else {
        p.clientPosition.add(velocity.clone().scale(deltaTime))
    }

我找不到其他方法以恒定速度进行插值。我从 gafferongames 开始了解 Hermite 插值。但很遗憾,这篇文章没有任何关于它的数学和实现的信息。我试图通过关于 Hermite 插值的维基百科文章,但它没有帮助。我对它背后的数学一无所知。一个伪代码将不胜感激。

到目前为止我能做到的事情:http://client-side-prediction-attempt.herokuapp.com/

【问题讨论】:

  • 不频繁的更新需要插值吗?你知道客户端会落后于服务器吗?
  • 服务器tick设置为100ms,所以我觉得有必要。是的,我知道由于插值,客户端会落后于服务器。现在,我只希望一切都显得顺利。
  • 你知道你从服务器获得的新点的速度吗?如果没有,你希望它如何表现?你对潜在的运动有一些了解吗(例如,速度是恒定的,只有方向改变)?
  • 我认为 Hermite 的插值不需要我发送速度。不过我确实寄给他们。速度的大小也会发生变化。

标签: javascript node.js algorithm networking hermite


【解决方案1】:

假设您的客户在时间currentTime 收到新的位置速度更新。然后,您需要保存当前位置/速度、目标位置/速度、当前时间以及您预计下次更新的时间:

function updateFromServer(position, velocity) {
    startP = currentPosition; //the current position of the player
    startV = currentVelocity;
    endP   = position;
    endV   = velocity;
    startT = currentTime; //the current time of the game
    endT   = startT + 0.1; //expect the next update in 100 ms
}

存储此数据后,您可以使用插值进行帧更新。如果您在[startT, endT] 区间之外,您可能只想继续匀速运动:

function frameUpdate(deltaT) {
    if(currentTime > endT)
        //uniform motion
        currentPosition += deltaT * currentVelocity;
    else {
        //cubic Hermite interpolation
        var t = (currentTime - startT) / (endT - startT); //interpolation parameter
        var t2 = t * t;
        var t3 = t2 * t;
        currentPosition = 
            (2 * t3 - 3 * t2 + 1) * startP + 
            (t3 - 2 * t2 + t)     * (endT - startT) * startV + 
            (-2 * t3 + 3 * t2)    * endP   + 
            (t3 - t2)             * (endT - startT) * endV;
        currentVelocity = 1 / (endT - startT) * (
            (6 * t2 - 6 * t)     * startP + 
            (3 * t2 - 4 * t + 1) * (endT - startT) * startV +
            (-6 * t2 + 6 * t)    * endP   +
            (3 * t2 - 2 * t)     * (endT - startT) * endV);
    }
}

请注意,此 sn-p 中的公式不是有效的 JavaScript 代码。它们必须被翻译成你使用的任何库。

【讨论】:

  • 你的sn-p中有'e'欧拉数吗?你从哪里得到的功能?我需要对算法进行更多解释。
  • e 是一个错字。这些公式是cubic Hermite spline 的公式。
  • 为什么对速度使用不同的函数?我不认为他们在维基百科页面上。
  • 我尝试将代码更改为此,但它看起来不像我预期的那样。我猜它仍然生涩。其他玩家在碰撞游戏边界时也会不断弹跳。
  • 速度函数是位置函数的导数。你是用秒来衡量时间的吗?如果您有不同的单位,则需要更改0.1。生涩是什么意思?您能否尝试将更新时间增加到 1 秒,以查看插值本身是否按预期工作?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 2023-03-04
  • 2016-06-24
相关资源
最近更新 更多