Jump to content

Multiplayer movement


Tufan
 Share

Recommended Posts

I'm working on a multiplayer game but player seems like teleporting when server sends new position.

How can i make movement smooth? Here's my movement algorithm:

Server (running every 1000/60ms):

    var updated = false;
    var speed = 300/60;
    if (this.player.cursors.up){
        this.y -= speed;
        updated = true;
    }
    if (this.player.cursors.down){
        this.y += speed;
        updated = true;
    }
    if (this.player.cursors.left){
        this.x -= speed;
        updated = true;
    }
    if (this.player.cursors.right){
        this.x += speed;
        updated = true;
    }
    if (updated){
        ...broadcast new x,y....
    }

Client:

var x = ..serverX..;
var y = ..serverY..;
sprite.x = x;
sprite.y = y;
sprite.nametag.x = x;
sprite.nametag.y = y - 110;

I want player to move 300 pixels a second. Is it possible to make it smooth?

-- sprite.nametag is a Phaser.Text object.

Link to comment
Share on other sites

Instead of pulling the client sprite position from the server and setting it directly, you might set it as a target and have the sprite handle itself moving to that position. For example, in pseudocode:

 

// server stays the same

// client:
var targetX = serverX;
var targetY = serverY;

// have `lerp` functions interpolate between current sprite position and target position, using whatever speed properties the sprite has
sprite.x = lerpX(targetX);
sprite.y = lerpY(targetY);
sprite.nametag.x = sprite.x;
sprite.nametag.y = sprite.y - 110;

Does that make sense?

Link to comment
Share on other sites

11 minutes ago, space_elevators said:

Instead of pulling the client sprite position from the server and setting it directly, you might set it as a target and have the sprite handle itself moving to that position.

I think it wouldn't work that way, in your example client movements might be delayed if server sends new target before sprite reach old target.

Link to comment
Share on other sites

43 minutes ago, space_elevators said:

The way I was thinking, targetX and targetY would be constantly changing as a character is moving - you won't wait for the sprite to reach targetX/Y before changing that target. I might be misunderstanding the issue you mentioned, though, and let me know if I am! :)

Client and server must have the same X,Y values synchronously.

In your way, server wants client to move to specific coordinates but have no idea where the sprite actually is. I'm handling everything on the server (includes collisions), client has one job to do: render game scene.

I'm working on a real-time shooter game (like diep.io) so i can't have target X,Y (can i?). I need the exact coordinates of sprite.

Link to comment
Share on other sites

What are you using on your server side and how do your client and server communicate? It sounds like you're limiting the answer to increasing the server <-> client speed, which is not really related to Phaser.

Even if you optimize your server <-> client speed, as far as I know space_elevators is right, that's how it's done in multiplayer games. That's why if you have a bad connection players can seem to move around smoothly but many hits won't be taken into account, that's one of the reasons why lag is annoying in multiplayer games.

The best solution, again as far as I know, is to interpolate between current position to last known position received from server, based on game-specific logic to make it look as smooth as possible.

The faster the server <-> client speed, the less noticeable the interpolation will be, it'll only be noticeable when server <-> client speed is bad, at which point you have no better option but to at least move the players around smoothly to make the lag experience more playable.

Naturally whenever you receive a new position from the server it overrides the previous position and the interpolation is recalculated.

Link to comment
Share on other sites

you can't achieve complete synchronicity with the server as there is always a delay, the client must render the move from A to B otherwise a slow connection would mean sprites just dart all over the place. At least with the client rendering the transitions you will only see whats called "rubber banding"

https://en.wikipedia.org/wiki/Rubber_banding

Link to comment
Share on other sites

Way 1: Handling all the movement on the client, sending x,y to the server every 100ms and doing some anticheat things on the server. (like transformice.com do)

Way 2: Handling movement on the server, moving entity on the client like space_elevators said.

Which way is better and why?

Link to comment
Share on other sites

Way 1:
It's gonna be very difficult to prevent cheating if the client is authoritative about its state. You could limit some things like teleporting across the map, but it wouldn't be possible to detect things like teleporting a small distance.

Way 2:
This would definitely make cheating more difficult, at least in regard to movement. But it's more complicated to implement.

In the end it depends on the type of the game and what you want to achieve. If the game gets popular, it's bound to have a lot of people trying to cheat – that's one thing to keep in mind.
Way 2 will also need stronger server.

Personally, I would go for way 2. Cheating can kill a game – that's basically the main reason. I wouldn't implement it in the way @space_elevators said though. That approach would cause visible lag and make the game borderline unplayable. I would use client-side prediction and server reconciliation techniques mentioned in the article in my previous comment. What @space_elevators described is called entity interpolation and is used for entities of other players, not the user's entity/character.

Other resources about this topic (though imho more difficult to understand, they do go more deeply into it):
Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization by Yahn W. Bernier from Valve.
What every programmer needs to know about game networking by Glenn Fiedler.
Real Time Multiplayer in HTML5 by Sven Bergström. I would start with this one. It's for HTML5 and Sven explains it really really well.

Link to comment
Share on other sites

You can see the source code:

http://www.gabrielgambetta.com/fpm_live.html

I'm using this for one of my projects in 3D, and it works very well, even if it's discouraged to do this instead of applying velocities to the physics-bodies.

You just have to validate the inputs, as there are still 2 ways to cheat using this:

#1: Send bigger deltas. If you're delta is 0.016 and you instead send 0.032, you move double the distance.

#2: Send more frequent updates. If you send 0.016 input deltas at 60Hz, you move the correct distance. What happens if you hack the client to send at 120Hz? You move at double speed again.

You'll have to cap the number of received movement inputs for each second (+/- some packet loss).

You'll have to limit the size of the delta timestamps, so if a client has a lag spike down to, let's say, 20FPS, this will be the absolute maximum size of the deltas, otherwise ignore them.

You can combine these two, so that if you receive ~60 inputs per second, the maximum delta timestamp to process will be 0.016.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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