Hello everyone, I'm using the arcade physics system from the HTML 5 game framework Phaser.
This is how I handle player movement:
Player 1 holds down W, sends velocity signal to server to move up. Player 1 moves up locally (so it's smooth), while the data is sent. The server basically relays that Player 1 pressed W and notifies everyone else in the game.
If Player 1 releases W, same thing happens, except players are notified the player has stopped. (body.velocity.x=0, body.velocity.x=0 run in client game loop). So basically, I'm relying on packets to change players velocities.. This isn't going to end well, eh? Keep reading please!
This works beautifully and doesn't use any interpolation and makes it seem so fast-paced and smooth (when players move around) -- I run an update interval on the client that sends their x, y positions periodically to keep their positions synced. So when a new player joins the game it'll take a second or so and they will become in sync. Obviously this isn't the best way to go about doing this, as it's SO easy to manipulate packets with browsers and so easy to send fake x, y values. All I can do is basically check the difference of their before and new position so they don't move too far (speed hacking) -- or just run a physics loop on the server. But honestly, I don't really care that much about speed hacking right now. I will in the future though, but right now I have a yuuuuge problem.
The problem is latency. I just tested it outside of my localhost server and wow, it all fell apart :(
From the example above:
When Player 1 releases W to notify all other players he stopped moving.. there is a, lets say 20-50, 100 ms lag. Or let's just say that there was a server hiccup that added 20ms.
This 20ms lag is now effected locally, by the clients physics. Which means...... Player 1 is actually not in the same position they are on their screen, as the view from other players. Because that extra ms of lag was used in the players local client (arcade physics) and added 20ms worth of velocity time. Which would be 10, 20, 30 extra pixels.
Now, I came up with a solution to this. When the player lets GO of W, I would send x, y values aswell (the position they stopped at), and then I interpolated those x, y values on every players screen so if there was any latency lag the player would "snap" to their real position. Basically a band-aid fix. This method is not smooth at all because the player would be "snapping back/to" their real x,y positions.
Positives:
- The real-time movement is insanely reactive and smooth
Negatives:
- Latency lag makes game unplayable unless over LAN
- When doing interpolation. Even at a 20hz server rate, the movement is still nowhere close to "real-time" as my above method. The interpolation makes it seem so "casual" and "non-responsive". Which I hate, and don't want.
- If a clients FPS drops to around 20, when they send the movement signal off, their player actually doesn't move that far. The duration of releasing and pressing W doesn't match where they are locally. You know this is bad when graphics are affecting the gameplay of other players. :P
Solutions:
- Run a physics loop on the server (60hz) for movement, and then a game loop at 20hz (that will periodically send new positions out 20/s) and then use interpolation.
- Downsides: Extreme server resources and bandwidth. I'm looking at around 20 packets per second, * 2 (up and down) for ONE player.
..and now I'm here asking what I can do. I've been reading into latency compensation:
But that looks like it would require a physics loop. And to have a physics loop on a nodejs server handling basic collisions at 60hz, would I be insane to do this?