我目前正在使用Phaser 3来表示服务器的状态。
每x时间,我会收到服务器的游戏状态,这就是客户端的样子:
var t1 = Date.now();
var serverUpdateDelta = 0;
Client.socket.on('usersPool', usersPool => {
// usersPool is an object containing all the user data of sockets connected on the server. Looks something like this:
/*
usersPool = {
"user1234": { x: 0, y: 0, direction: "right", moving: true },
"testuser": { x: 200, y: 250, direction: "down", moving: false }
}
*/
// keeping count of milliseconds between updates (usually around 500m)
serverUpdateDelta = Date.now() - t1;
// for every user connected on the server...
for(id in usersPool) {
let data = usersPool[id]; // this is the user's data
if(/* the player exists as a sprite in the game...*/) {
// THIS IS WHERE THE MAGIC SHOULD HAPPEN
} else {
genSprite(player);
}
}
});
玩家的数据包含一个movementQueue
,它只是用户所在的坐标数组。可能看起来像这样:
[
{ x: 0, y: 0, direction: 'down', moving: false },
{ x: 5, y: 0, direction: 'right', moving: true },
{ x: 6, y: 0, direction: 'right', moving: false }
]
这是在服务器上计算的,但是每个movementStack
(motionQueue中的项目)每25毫秒左右在服务器上生成一次。
现在的工作是,在接收到该motionQueue时,对这些值进行插值并相应地移动精灵...
我首先尝试制作一个在收到更新后便会插值的函数,如下所示:
// THIS IS WHERE THE MAGIC SHOULD HAPPEN
// user's state on the client is set to an interpolated version of the one on the server
player.movementQueue = buffer(data.movementQueue);
缓冲区将仅基于serverUpdateDelta和game.loop.actualFps生成插值数组
然后,在Game.update函数中,运行以下命令:
for(id in spawnedPlayers) {
// this will remove the first movementStack from the queue and returns in
movementStack = spawnedPlayers[id].movementQueue.shift();
// we then take this movementStack and update the user to that position (and play the walking animation)
spawnedPlayers[id].update(movementStack);
}
因此,每个游戏循环,我们都会从队列中删除一个堆栈并将用户设置为该堆栈。
这不起作用。游戏循环的运行次数似乎比队列中的帧多得多,这使玩家看起来好像他们在缓慢移动一小段距离... * :
player.movementQueue = player.movementQueue.concat(buffer(data.movementQueue));
但是随后发生了一些奇怪的事情,游戏循环无法跟上移动队列的速度,玩家移动得非常缓慢...
然后我尝试使用补间,它非常容易实现,只需运行:
// THIS IS WHERE THE MAGIC SHOULD HAPPEN
_this.tweens.timeline({
targets: player.sprite,
tweens: data.movementQueue, // [{x, y}, {x, y}, {x, y}]
duration: serverDeltaTime/movementQueue.length, // duration between each tween in ms
});
除了一个小细节之外,这完美地实现了ALMOST:
之前,我们将在每个MovementStack上为播放器运行一个方法:player.update(movementStack)
,该方法将采用用户的指示并相应地对精灵进行动画处理。现在我们无法执行此操作...
SO
我可以使用哪些方法或技术?我想念什么?我可以实施什么?我问这个问题是因为我被困在这一点上。
预先感谢您的帮助。