Workshop 1: Dead Reckoning Template


In this Workshop you will learn, how to use the Dead Reckoning Template. The Dead Reckoning Template not only supports the Dead Reckoning Algorithmus, but also a Client Update Range that allows you to receive data from entities only in a given range around the player entity of a client -> reduction of traffic.
For using the template in your project, include #include "dr_template.c" after #include "anet.h" in your main script file.

What is Dead Reckoning?


Dead Reckoning is an algorithm that is used for position updating. Instead of permanent sending the position of an entity (like in the 3D Chat Tutorial), the algorithm "guesses" where the entity moves. Because of this, less data must be sent. Only with a good Dead Reckoning Algorithm, games with a lot of moving entities (like egoshooter) get playable over the internet.
But not every DR algorithm can be used for everything. The algorithm that is used in this template is suitable for players and other moving entities that are using c_move() (Gamestudio Manual for details) for their movement. Entities that are controlled by the physic engine can't use this algorithm.
Additionally you should consider, that only the pan angle gets updated, because the Tilt and Roll angles aren't used by e.g. player entities and this would only cause more traffic.

Usage without Client Update Range


The plain usage of the template is using the DR algorithm without a Client Update Range. But the Client Update Range is turned on for default. Because of this, it has to be turned off at the beginning. For this you have to search the following line in your "dr_template.c" file:

#define dr_update_range 50000 //should be a bit bigger than camera.clip_far; 0 means no update range is used

Now change the value 50000 to 0. Probably you are currently asking yourself what the other constants are for. They are described below.
In your code a server should be initialized and it should be possible to connect a client with it. On both hosts, the same level should be loaded. You should already know how you can implement something from the 1. HowTo and the 3D Chat Tutorial.
The client now creates an entity that calls e.g. this function:

//Lite-C:
function player_func()
{
VECTOR dist_move;

while(enet_ent_globpointer(my) == ANET_ERROR) {wait(1);}

if(enet_ent_creator(enet_ent_globpointer(my)) == enet_get_clientid())
{ //Creator part
use_dr();
while(1)
{
my.pan -= 25*mouse_force.x*time_step;
dist_move.x = 15*(key_w-key_s)*time_step;
dist_move.y = 15*(key_a-key_d)*time_step;
dist_move.z = 0;

dr_c_move(me,dist_move,nullvector,IGNORE_PASSABLE+GLIDE);

//controls the camera
camera.x = my.x-100*cos(my.pan);
camera.y = my.y-100*sin(my.pan);
camera.z = my.z+50;
camera.tilt += mouse_force.y;
camera.pan = my.pan;
if(camera.tilt < -50) {camera.tilt = -50;}
if(camera.tilt > 20) {camera.tilt = 20;}
wait(1);
}
}
else
{
dr_ghost();
}
}

The function waits for the global pointer of the entity. After that the function is split into 2 parts: The first part is called from the creator of the entity and the second one from all the other hosts.

Now let's look into the first part: dr_use(); tells the template, that the entity is using the DR algorithm from now on. After that the input of the user is evaluated and the entity is moved. For this the function dr_c_move() needs to be used. The function works exactly like c_move, but makes use of the DR algorithm. Then the camera is placed behind the player (3rd person).

In the second part the function dr_ghost(); tells the template, that the entity should accept data from the DR algorithm. The position and the pan angle of the entity is now updated automatically.

Settings


The template offers some parameters for setting up the template.

#define dr_angle_sensitive 5
#define dr_ang_update_rate 4
#define dr_pos_update_rate 0.5
#define dr_max_players 32
#define dr_update_range 50000

Parameter Description

dr_angle_sensitive Angles that have changed in this tolerance aren't sent. Because changes of the angle of some degrees aren't always noticeable, traffic can be saved here. A too big tolerance can cause a lagging rotation.

dr_ang_update_rate Number of pan updates that should be sent per second if the pan changes.

dr_pos_update_rate Number of position updates per second if the position of the entity has change (0.5 = all 2 seconds). This is executed beneath the normal DR algorithm for correction purpose.

dr_max_players Max. player number of your game (only used when Client Update Range is enabled).

dr_update_range Range (in quants) around the player entity of a client, where updates of entities are received. All entities out of this range are set to invisible and passable and cause no traffic on the client. Because of that the range should be bigger than the clip_far range. If this value is set to 0 no Client Update Range is used.


Please notice that data is only sent, if they have changed => If an entity isn't moving, it causes no traffic. The default values are those values, which gave the best results during testing. But they depend on what you are using the template for. Because of this you should experiment yourself with those values and use those, that give you the best result.

Usage with Client Update Ranges


If you want to use a Client Update Range you have to set dr_update_range to a range in quants where entities should be updated around the player entity. You should use a value that is a bit bigger than the value you have chosen for clip_far, so that the entities don't appear suddenly.
Additionally the function dr_control_updateranges() has to be started on the server. This function manages the Client Update Ranges.

In the function of the entity you have to add the bold print function:

//Lite-C:
function player_func()
{
VECTOR dist_move;

while(enet_ent_globpointer(my) == ANET_ERROR) {wait(1);}

if(enet_ent_creator(enet_ent_globpointer(my)) == enet_get_clientid())
{
dr_player(my);
use_dr();
while(1)
{
my.pan -= 25*mouse_force.x*time_step;
dist_move.x = 15*(key_w-key_s)*time_step;
dist_move.y = 15*(key_a-key_d)*time_step;
dist_move.z = 0;

dr_c_move(me,dist_move,nullvector,IGNORE_PASSABLE+GLIDE);

//controls the camera
camera.x = my.x-100*cos(my.pan);
camera.y = my.y-100*sin(my.pan);
camera.z = my.z+50;
camera.tilt += mouse_force.y;
camera.pan = my.pan;
if(camera.tilt < -50) {camera.tilt = -50;}
if(camera.tilt > 20) {camera.tilt = 20;}
wait(1);
}
}
else
{
dr_ghost();
}
}

The function dr_player(my) tells the server that the passed entity is the player entity of the client. Every client has to set a player entity. The update range is measured from this entity. If no player entity is set, no update range is used on the client.