Phaser 3 - Sprite linear interpolation using movement queue











up vote
0
down vote

favorite












I'm currently using Phaser 3 to represent my server's state.



Every x amount of time, 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...*:



player.movementQueue = player.movementQueue.concat(buffer(data.movementQueue));


But then something weird happened, where the game loop could not keep up with the movementQueue and the player would move extremely 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.










share|improve this question




























    up vote
    0
    down vote

    favorite












    I'm currently using Phaser 3 to represent my server's state.



    Every x amount of time, 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...*:



    player.movementQueue = player.movementQueue.concat(buffer(data.movementQueue));


    But then something weird happened, where the game loop could not keep up with the movementQueue and the player would move extremely 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.










    share|improve this question


























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I'm currently using Phaser 3 to represent my server's state.



      Every x amount of time, 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...*:



      player.movementQueue = player.movementQueue.concat(buffer(data.movementQueue));


      But then something weird happened, where the game loop could not keep up with the movementQueue and the player would move extremely 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.










      share|improve this question















      I'm currently using Phaser 3 to represent my server's state.



      Every x amount of time, 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...*:



      player.movementQueue = player.movementQueue.concat(buffer(data.movementQueue));


      But then something weird happened, where the game loop could not keep up with the movementQueue and the player would move extremely 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.







      javascript game-physics phaser-framework linear-interpolation






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 20:25









      James Skemp

      4,81274775




      4,81274775










      asked Nov 10 at 0:38









      JohnCdf

      86113




      86113





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234989%2fphaser-3-sprite-linear-interpolation-using-movement-queue%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234989%2fphaser-3-sprite-linear-interpolation-using-movement-queue%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Schultheiß

          Verwaltungsgliederung Dänemarks

          Liste der Kulturdenkmale in Wilsdruff