4

I just made a multiplayer browser implementation of the game Pong using socket.io and have a question regarding logistics of real time. Basically the player's paddle is just a colored-in div that moves up or down depending on which button they're pressing. I noticed when testing my program with two different computers using AWS that the movement was nearly perfectly synchronized but sometimes not exact. For the player that controls the paddle, the movement of their paddle is done locally, but for the person they're playing against the server continuously sends them data of whether their opponent moved up or down.

My question is should I be doing all the movement server-side? Like a user presses to go up and it sends the server a request which emits to both players that the paddle should move, or is my way where movement for your paddle being done locally fine?

My code right now looks like this:

Client-side checking if up or down button pressed and emitting move request:

paddleMove = 0; // Keep track of which direction to move
speed = 5; 
    if (paddleL.position().top > arena.position().top){ // If left paddle not at top
        if (keysPressed.up) paddleMove -= speed;
    }
    if (paddleL.position().top+paddleL.height() < arena.position().top + arena.height() - 15){ // If left paddle not at bottom
        if (keysPressed.down) paddleMove += speed;
    }
    paddleL.css({  // Move paddle locally
        top: paddleL.cssNumber('top') + paddleMove + 'px'
    });
    socket.emit("moveReq", paddleMove); // Send to server 

The above code is in an interval that runs every fraction of a second.

Then the server side looks like this:

socket.on('moveReq', function(data){   // Send to opponent that other paddle moved
    socket.broadcast.emit("movePaddle", data);
});

Which in turn alerts another portion of the user-side code to move the other paddle:

socket.on("movePaddle", function(data){

        var paddleMove = 0;
        paddleMove += data; // Data is speed (direction) of movement
        paddleR.css({ // Move right paddle
            top: paddleR.cssNumber('top') + paddleMove + 'px'
        });

As I said, the movement right now is pretty good but not perfect. Should I make none of the movement local and make it all on a server emit?

MarksCode
  • 8,074
  • 15
  • 64
  • 133
  • Imo you should do movements at client side and sync with server side at specific times, in this case when ball touch paddle, so you will prevent to overload the server and prevent hacking. – Henri Cavalcante Mar 21 '16 at 22:03

2 Answers2

4

Currently i am even working on multiplayer game using web sockets . If you want real time player position then it will take lot bandwidth.

So far what we i did was prediction and lerping . Suppose there are two players connected named A & B .

Lets say Player A by default is on x=0 (t=0) , so on B it will be also on x=0. Now what will we do is will start emiting A's x-positon every 1 sec (depending on your game , if fps then lower the value )

After 1 sec (t=1), A's position is on x=2 (2px according to you). B receives the position of A after 1.2sec (considering late due to network issues) . Now we have to lerp the position from x=0 to x=1 predicting the time . (This all can be achieved with scripting )

Basic Formula (This will be done in a update function) :

CurrentXposition = (NewXPosition - CurrentXPosition) * deltatime ;

Well you have to definitely work on the above formula . The deltatime will be calculated every time when we receive new position . So here we lerp and predict all in one using deltatime .

Lerping will smooth the movement of player , and deltatime which will work as prediction will set the correct time and smoothness of lerping according to received position .

Refer this blog for more into this ,

And This for lerping formula

Community
  • 1
  • 1
Akira Lynn
  • 394
  • 3
  • 14
  • thanks for this. I'm having some trouble though. I am sending the `NewXPosition` out every 250ms or so, but when interpolating, the character "jumps" if you will, whenever the `NewXPosition` gets updated. Am I supposed to be sending the new lerping value the same rate as the games fps? – NiCk Newman Jun 08 '16 at 02:21
  • 1
    You can handle the position sync in two ways. One is by sending the the position 10 frames per second or by the key press . You have to calculate the deltaTime when you receive each frame using the timestamp . i.e. the time elapsed from previous frame , the difference between the update rates of your game , and the also you have to use some logic for lerping to simulate the physic. – Akira Lynn Jun 10 '16 at 14:27
2

Update the position immediately on the client side. Then send the movement message to the server. When you get a message back from the server sync the position to the server's value.

This way the client movement should still seem smooth on flaky or high latency connections. However in some extreme cases the client may be so much out of sync that the paddle will appear to be in a position that it's not (the ball may appear to go through the paddle) - though either way a high ping is going to solve problems

Kable
  • 1,035
  • 8
  • 18