Workshop 1: Dead Reckoning Template


In diesem Workshop wird Ihnen erklärt, wie Sie das Dead Reckoning Template verwenden können. Das Dead Reckoning Template unterstützt neben dem Dead Reckoning Algorithmus eine Client Update Range die es erlaubt, Daten von Entities nur in einer gewissen Reichweite zu empfangen -> Reduzierung des Traffics.
Um das Template in ihrem Projekt verwenden zu können, fügen Sie einfach #include "dr_template.c" nach #include "anet.h" in Ihrer main Skriptdatei ein.

Was ist Dead Reckoning?


Dead Reckoning ist ein Algorithmus der zur Positionsaktualisierung verwendet wird. Statt dem andauernden Senden der Position einer Entity, "rät" der Algorithmus wohin sich die Entity bewegen wird. Dadurch müssen weniger Daten gesendet werden. Erst durch einen guten Dead Reckoning Algorithmus werden Spiele mit vielen bewegten Entities (wie Egoshooter) über Internet spielbar.
Leider lässt sich nicht jeder DR Algorithmus für alles verwenden. Der Algorithmus, den dieses Template nutzt, eignet sich hervorragend für Spieler und sonstige bewegten Entities die c_move() (siehe Gamestudio Manual) zum Ausführen der Bewegung nutzen. Entities die von der Physikengine gesteuert werden, können diesen Algorithmus nicht verwenden.
Weiters ist zu beachten, dass nur der Pan Winkel aktualisiert wird. Da die Winkel Tilt und Roll bei z.B. Spielern sowieso nicht benötigt werden, würde dies nur unnötig viel Traffic verursachen.

Verwendung ohne Client Update Range


Der "unkomplizierteste" Betrieb des Templates ist die Nutzung des Dead Reckoning Algorithmusses ohne Client Update Range. Diese ist jedoch standardmäßig eingeschaltet. Darum muss sie zu Beginn deaktiviert werden. Suchen Sie dafür folgende Zeile in der "dr_template.c" Datei:

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

Ändern Sie nun den Wert 50000 auf 0. Sie fragen sich wahrscheinlich gerade, wofür die ganzen anderen Konstanten gut sind. Diese werden weiter unten erklärt.
In Ihrem Code sollte nun ein Server initialisiert werden, mit dem Sie einen Client verbinden können. Auf beiden Hosts sollte das selbe Level geladen werden. Wie Sie das alles realisieren können, sollten Sie bereits aus dem 1. HowTo und aus dem 3D Chat Tutorial wissen.
Der Client erstellt nun eine Entity, die zum Beispiel folgende Funktion aufrufen könnte:

//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();
}
}

Die Funktion wartet zuerst darauf, dass die Entity einen globalen Pointer erhält. Danach wird sie in 2 Teile gespalten: Der 1. wird von dem Ersteller der Entity ausgeführt, der 2. von allen anderen Hosts.

Sehen wir uns den 1. Teil an: dr_use(); teilt dem Template mit, dass diese Entity ab sofort den DR Algorithmus nutzt. Danach wird die Eingabe des Benutzers ausgewertet und die Entity bewegt. Dafür gibt es die Funktion dr_c_move(). Sie funktioniert genau so wie das normale c_move, wird jedoch benötigt wenn der DR Algorithmus benutzt wird. Als letztes wird die Kamera hinter den Player platziert (3rd Person Ansicht).

Im 2. Teil der Funktion wird dem Template mitgeteilt, dass die Entity Daten von einen DR Algorithmus zugesendet bekommt. Die Position und der Pan Winkel der Entity wird nun automatisch aktualisiert.

Einstellungen


Das Template bietet einige Parameter, mit denen es konfiguriert werden kann:

#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 Beschreibung

dr_angle_sensitive Winkel die sich innerhalb dieser Toleranz verändert haben, werden nicht gesendet. Da Änderungen des Winkels von ein paar Grad nicht immer merkbar sind, kann hier Traffic eingespart werden. Eine zu große Toleranz kann eine stotternde Drehung bewirken.

dr_ang_update_rate Gibt an wie oft der Pan einer Entity während er sich ändert pro Sekunde gesendet werden soll.

dr_pos_update_rate Gibt an wie oft die Position einer Entity bei einer Änderung pro Sekunde gesendet werden soll (0.5 = alle 2 Sekunden). Dies geschieht als eine art Korrektur neben dem noramlen Senden der DR Daten.

dr_max_players Maximale Spieleranzahl ihres Spiels (wird nur bei Client Update Range verwendet).

dr_update_range Gibt die Reichweite (in Quants) an, in der rund um den Player des Clients, Entities geupdated werden sollen. Alle Entities die außerhalb dieses Bereiches sind, werden auf dem Client unsichtbar und passabel gemacht und verbrauchen praktisch keinen Traffic mehr. Darum sollte dieser Bereich außerhalb des clip_far Bereiches liegen. Wird dieser Wert auf 0 gesetzt, so wird die Client Update Range deaktiviert.


Bitte beachten Sie, dass Daten immer nur dann geupdated werden, wenn sie sich verändert haben. D.h. wenn sich eine Entity nicht bewegt, verbraucht sie auch keinen Traffic. Die Standardwerte sind die Werte, die sich bei den Tests als am sinnvollsten herausgestellt haben. Dies kann jedoch vom Anwendungsfall abhängen. Darum sollten Sie selbst mit diesen Werten experimentieren, und die Werte wählen, mit denen Sie das beste Ergebnis erzielen können.

Verwendung mit Client Update Ranges


Wenn Sie die Client Update Ranges verwenden möchten, müssen Sie dr_update_range auf die Reichweite in Quants setzen, in der die Entities rund um der Spielerentity eines Clients aktualisiert werden sollen. Sie sollten dafür einen etwas größeren Wert als clip_far wählen, damit die Entities nicht plötzlich verschwinden.
Weiters muss die Funktion dr_control_updateranges() am Server gestartet werden. Diese Funktion verwaltet die Client Update Reichweiten.

In der Funktion der Entity müssen Sie noch die Fett gedruckte Funktion ergänzen:

//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();
}
}

Die Funktion dr_player(my) teilt dem Server mit, dass die übergebene Entity die Spielerentity des Clients ist. Jeder Client muss also eine Spielerentity definieren. Die Reichweite wird von dieser Entity aus gemessen. Wird keine Spielerentity angegeben, so wird auch keine Reichweite verwendet.