相位器3-使用运动队列进行精灵线性插值

时间:2018-11-10 00:38:08

标签: javascript game-physics phaser-framework linear-interpolation

我目前正在使用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时,对这些值进行插值并相应地移动精灵...

尝试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
  });

除了一个小细节之外,这完美地实现了ALMOST:

之前,我们将在每个MovementStack上为播放器运行一个方法:player.update(movementStack),该方法将采用用户的指示并相应地对精灵进行动画处理。现在我们无法执行此操作...

SO

我可以使用哪些方法或技术?我想念什么?我可以实施什么?我问这个问题是因为我被困在这一点上。

预先感谢您的帮助。

0 个答案:

没有答案