This week’s focus was on lag compensation for carrying objects. However I got stuck with delay when throwing an object.
When the player is carrying something (including the Felicie), the item is switched to skip interpolation, meaning that it is not part of the 100ms lag of other objects, so it appears responsive. The problem arises when the player throws the object. There’s a delay between the sending of the throw command and the first server response showing the result. The 100ms lag compensation delay induced when switching off skip interpolation was subdued by recalculating from the render tick (which is 100ms in the past) to the present tick and also sending them to server. But there is still the transmission delay.
Something I will be working on next week is trying to get rid of this delay by letting the remote player simulate the throw similar to how we’re handling input prediction. For input prediction we are
- doing the player movement simulation,
- sending the keypress together with the x,y coordinates as calculated by the remote client to the server (and keeping track of the position and the current tick)
- the server replies with its own calculation according to the keypress
- the remote client verifies if its calculations match with the server and if it doesn’t it will correct the position.
We need to do something similar for the throw. The only difference is that no keypresses are done
This week was focused on getting lag compensation in place, and I focused on two specific events which should be to appear as responsive as possible, namely picking loot and landing on enemies’ head.
So remember that the player is seeing the world 100ms behind, but his avatar is updated immediately thanks to Input Prediction which was done last week. When picking up loot, it needs to be verified by the server. When avatar touches a loot, it sends a request to the server with the current render tick (~100ms behind). The server will go back in time to verify that he can take the loot, and reply with a yes/no answer.
The landing on an enemy head (and killing him) is slightly more complicated, namely because it we create a dead body instance that flies off from the position of the killing. So if it is accepted by the server, we need to simulate back in time to the current time for both the server and the client, since they are both rendering 100ms behind.
Since a lot of data structures are involved in making this possible, it was inevitable that I would do some typo or other stupid mistake. And this is where I miss Unity and it’s strong typed C#. In GameMaker you can do anything and it will not check for you. So for example you can delete a buffer instead of a list and it will not complain but will obviously corrupt the memory and then you start having all kind of weird crashes. I would accept this in a compiled released version where all checks are removed, but I was surprised no checks at all are being done in the debug VM version. Because of this, I think this will be my first and last project on GameMaker.
This week I focused on getting input prediction working. What I had working last week, I had the remote player pressing keys, sending them over to the server and waiting for the server to reply back with the next state of the player. Adding the 100ms delay for interpolation purposes you would have 100ms + ping time before you see your character move. That’s pretty bad as the game would feel very laggy.
What Input Prediction does is that the remote player’s avatar will appear moving immediately as if it’s a non-networked game. It will save the key strokes requests sent to the server by giving them an id together with the predicted position. The server will receive these key stroke requests, and will reply back with the resulting position as calculated by the server. The remote client will then receive these server-verified positions and double check if the positions calculated for that key stroke request matched or not. If it doesn’t match then it will start fixing the position according to what the server calculated.
The next part of the puzzle for next week is Lag Compensation. This will solve the issue for having events (like picking up loot or killing enemies) appear more responsive.
Pyramid Plunge already has local multiplayer implemented. It’s not cooperative as most have thought. It’s actually a competitive game where each player controls their own George+Felicie. The player who exits the level with the most coins wins. To make it more interesting you can steal the coins from the other player by throwing objects to the other player were half their coins will spew out of them ala Sonic. You cannot harm your opponent though as otherwise the game would be over pretty soon. The first one to exit triggers the flood and also becomes the jellyfish so he can hunt down the other player.
These last couple of weeks I decided to bite the bullet and start implementing online multiplayer. I know there is Steam Remote Play Together to play a local multiplayer game online, but there will be a bit of delay on the remote player since he’s basically streaming the game from the other player.
I’m following the basic principles outline in the Source Engine multiplayer, and I’m using peer-to-peer server-client architecture. The server will be authoritative, so whatever the server says is legit. The client will basically be a dummy client sending keystrokes 30 times per second, and the server sends world updates 20 times per second. I got that working so far with entity interpolation in place. So the next thing I will be working on next week will be input prediction to make it feel more responsive on the client side.