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.
javascript game-physics phaser-framework linear-interpolation
add a comment |
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.
javascript game-physics phaser-framework linear-interpolation
add a comment |
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.
javascript game-physics phaser-framework linear-interpolation
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
javascript game-physics phaser-framework linear-interpolation
edited Nov 10 at 20:25
James Skemp
4,81274775
4,81274775
asked Nov 10 at 0:38
JohnCdf
86113
86113
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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