我目前正在使用 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);
}
}
});
玩家的数据包含 a 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
(movementQueue 中的项目)在服务器上每 25 毫秒左右生成一次。
现在的工作是,当接收到这个移动队列时,插入值并相应地移动精灵......
尝试 1
我首先尝试制作一个在收到更新后进行插值的函数,如下所示:
// 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));
但后来发生了一些奇怪的事情,游戏循环跟不上移动队列,玩家移动得非常慢......
尝试 2
然后我尝试使用非常容易实现的补间,只需运行:
// 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
});
这几乎完美地工作,除了一个小细节:
之前,我们会在每个 moveStack: 上为玩家运行一个方法player.update(movementStack)
,该方法将获取用户的方向并相应地为精灵设置动画。现在我们没有办法做到这一点......
所以
我可以使用哪些方法或技术?我错过了什么?我能实现什么?我问这个是因为我被困在这一点上。
预先感谢您的帮助。