In my previous news post "Client features
", I talked about several important client features and how
they have recently been improved.
As promised there, although this is rather a technical documentation than
suitable prose for a news post, I would still like to provide a brief overview
on how the previously covered features work and how they interact with each
As implemented in class
, a client
that has joined a game world has these crucial tasks to complete in each video
// Draw the current state of the game world on screen.
// Everything else that is important in each game loop:
// - process any network packets that might have arrived from the server
// (apply server updates and run reprediction as described below),
// - collect and process player input.
For a start, we can assume that the
method (and any nested
are responsible for rendering the client world are "constant". As explained
later, this is not exactly true in the strict sense of the C++
keyword, but it
true in the sense that when the drawing is done and the
method returns, the client's world state is exactly
the same as it was
when the drawing began.
That leaves the client's main loop (
to be considered.
message arrived from the server, all game entities (that are relevant for the
client) are updated to the state of server frame "X". As the server also
indicates the growing ID of our client's player command that it has accounted
for up to server frame "X", the locally available player commands that have not
yet been accounted for since frame "X" are re-applied ("reprediction").
Player input from mouse and keyboard is collected in each video frame and
stored in a
struct. It then
- sent to the server (for the server's authoritative processing),
- "predicted": applied locally and stored for future reprediction,
- cleared (for the next loop iteration).
At this point, it is important to note that the above described client
implements full networking support with prediction and reprediction, but not
yet with any of the extra features mentioned in my previous
Especially note that the client's game world is always in state "X" as last
received from the server, where additionally the local player input is applied
to the client's player entity.
Adding Interpolation, Reconciliation and Client
The crucial idea is that our client world is generally always
the above described state: latest server state "X" + prediction.
This is a very important invariant of the prediction feature, because
otherwise, if interpolation or other effects modified the world state, the
prediction would find a different state when locally applying player input than
the server would, which in turn introduces stuttering as it breaks the
we make sure to (only) take note
of anything that might affect the
effects. Most prominently, if a new
arrives, new target values for the interpolations are recorded – but the values
themselves are updated as if interpolation didn't exist.
The last piece of the puzzle is in
, which is
actually responsible for rendering the world:
- it activates the interpolation, reconciliation and client effects,
updating all variables to their proper values,
- renders the world in the prepared state,
- restores the previous values back to "latest server state X +
Besides the processing of incoming server updates and outgoing player input,
the client has a lot more to accomplish before a good game experience can be
rendered. The key idea is to keep the client's world state always at the latest
received server state "X", with local prediction applied.
Interpolation, reconciliation and client effects are kept and maintained
independently. Although the code for these features affects several source
files, this encapsulation helps with readability and correctness.
In this regard, we now have a very good and powerful framework. It is used to
implement several important examples already, and I hope to utilize these
facilities more often and more extensively in the future – I can still think of
a lot of effects that I would like to see but that aren't there yet, e.g. head
bopping when the player is walking or running, rotating items, swinging and
flickering light source, and so on.
As always, your comments, feed-back or help are very much appreciated!