Jump to content

Phaser 3 inlinear interpolation help


SKEPDIMI
 Share

Recommended Posts

Hello, Phaser3! I'm new to game development and have been using the library to make a 2d multiplayer game, however, I did run into an issue when attempting to synchronize the server state with the client state using linear interpolation to smooth out movement of sprites between points. I'm pretty stuck

#  ----

# TL;DR

I need a way to interpolate a user to different coordinates in the map while animating the sprites according to the data given. Example:

socket.on('user_data', data=> {
  let player = spawnedUsers[data.id];



  player.smoothToAllCoordinatesAndPlayAnimations(data.movementQueue);

})

// movementQueue looks something like this:

    [
      { x: 0, y: 0, direction: 'down', moving: false },
      { x: 5, y: 0, direction: 'right', moving: true },
      { x: 6, y: 0, direction: 'right', moving: false }
    ]

#  ----

Every 50ms I am sent the server's game state, this is what the client looks like:

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


The player's data contains a `movementQueue`, which is just an array of coordinates the user has been at. It might look a little like this:

[
      { x: 0, y: 0, direction: 'down', moving: false },
      { x: 5, y: 0, direction: 'right', moving: true },
      { x: 6, y: 0, direction: 'right', moving: false }
    ]

This is calculated on the server, but each `movementStack` (item in the movementQueue`) is generated every 25 milliseconds or so on the server.

The job now is, when receiving this movementQueue, to interpolate the values and move the sprite accordingly...

-> Attempt 1

I first tried making a function which would interpolate once the update was received, like so:   

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


The buffer will simply generate an interpolated array based on the serverUpdateDelta and game.loop.actualFps

then, in the Game.update function I ran the following:

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

So every game loop, we would remove a stack from the queue and set the user to it. 

This did NOT work. The game loop seemed to run Way more times than there were frames in the queue, making the player look like they were moving a small distance very slowly.

-> Attempt 2

I then tried using tweens which would be really easy to implement, simply run:

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

This worked ALMOST perfectly, except for one small detail:

Before, we would run a method for the player on each movementStack: `player.update(movementStack)`, this method would take the direction of the user and animate the sprite accordingly. Now we have no way of doing this... 

SO

What methods or techniques could I use? What am I missing? What could I implement? I ask this because I'm stuck at this point.

Thank you in advance for the help

John S.
 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...