实施Hermite插值 - 多人游戏



我正在尝试制作客户端服务器体系结构。我被困在插值部分。目前,我对插值算法的实现非常幼稚。我有每个玩家都给出了一个位置历史记录,每当我从服务器中收到其他播放器的位置数据时,我都会将位置推入该数组。我使用最古老的位置历史记录以恒定速度插入新位置。

// 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))
    }

我找不到其他方式以恒定的速度插值。我开始知道从混乱的人中插值。但是,这篇文章对其数学和实施一无所知,这是可悲的。我试图浏览有关Hermite插值的Wikipedia文章,但这无济于事。我对背后的数学一无所知。伪代码将不胜感激。

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

假设您的客户在时间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);
    }
}

请注意,该片段中的公式不是有效的JavaScript代码。它们必须翻译成您使用的任何库。

相关内容

  • 没有找到相关文章

最新更新