Righto, two questions for you brain boxes tonight - one about frame rate independent movement for players and one about angles.
Framerate:
I read the DBP timer tutorial in the newsletter way back and made myself a set of timer functions based off it, also some others based on ideas from the irc channel. The idea being to get a factor I can times the desired speed at 30fps at so no matter the framerate all players move the same speed on all machines. VITAL because im working on a multiplayer action game - sync must be kept.
I always suspected my system was allowing a bit of variation in when I was having a deathmatch with my friend, but it didnt seem too bad. However i have rewritten my entire network engine to something a bit more sensiable, effective and hacker proof - now the clients send keystates to the server and the server moves the objects locally and broadcasts their state on a timer, the players predict movement then using something simular to cubic splines. I wrote the prediction today and it was all buggered, first i thought it was the prediction (which i know isnt right yet, see angles section) but then for a test i just positioned the player at the position in the packets its receiving so i could see where he should be by where he jumps to - he was flying across the map at insane speeds.
The server is a darksdk application but doesnt draw objects, has backdrop disabled etc and for maxium processing effcientcy has an uncapped sync rate - the moment i capped the sync at 60 the player speed became normal again. Not a solution, i need that frame rate uncapped! Has anyone ever implemented framerate independent code that they KNOW truely is the same speed on all computers? heres my code.
At the start of each frame, i call these two functions in this order:
GetAdverageFps();
UpdateTime();
the code for these is:
float GetAdverageFps() {
float fTemp = 0.0f;
for (int n = 0; n < MAX_ADV; n++) {
fTemp += Adverages[n];
}
fAdverageFps = fTemp / MAX_ADV;
return fAdverageFps;
}
void UpdateTime() {
for (int n = 0; n < MAX_ADV - 1; n++) {
Adverages[n] = Adverages[n + 1];
}
Adverages[MAX_ADV - 1] = fTime;
if (dbTimer() - nLastTicks > 1)
fTime = 1000.0f / (dbTimer() - nLastTicks) * 1.0f;
fAdrTime = (dbTimer() - nLastTicks) / 1000.0f;
nTicks = (dbTimer() - nLastTicks);
nLastTicks = dbTimer();
}
then, when the server is about to move a player it calculates the speed like this:
float fFactor = GetFactorOnAdverage();
if (fFactor > 1.0f) {
fFactor = 1.0f;
}
float fSpeedFactor = aPlayerStates[n].fSpeed * fFactor;
the fSpeed member of aPlayerStates is the const speed for that tank in its current state. GetFactorOnAdverage() simply looks like:
float GetFactorOnAdverage() {
return 30.0f / fAdverageFps;
}
I didnt used to calculate a factor off the adverage, but after testing many things that seemed the best on the client which never ran past 60fps anyway. Where am I going wrong?
Angles:
This is about the player prediction - whenever a new state packet arrives with position information the players start getting moved towards that point. The first thing I do is calculate the angle between the players current point and its destination point so i can rotate the player towards it smoothly. First question is, am I even using arctan right? The docs are really unhelpful with this command:
float fDestAngle = dbAtanFull(aPlayerStates[nPlayer].vDest.x - aPlayerStates[nPlayer].fPlayerX,
aPlayerStates[nPlayer].vDest.z - aPlayerStates[nPlayer].fPlayerZ);
Secondly, when I have the destination angle, I turn the player towards it using dbCurveAngle - it seemed like a good idea at the time >.> The function gets called every frame so it seemed right. However, the docs specify that the first parameter is the destination, the second parameter is the.. curve.. i presume current angle and the third parameter is the speed. However the docs also say CurveAngle is CurveValue >.> So I opened the header and that says: dbCurveAngle( float a, float da, float sp ); - im presuming a is current angle, da is destination angle and sp is the speed, the oposit way around from the docs. Currently I am using:
aPlayerStates[nPlayer].fPlayerBaseR = dbCurveAngle(aPlayerStates[nPlayer].fPlayerBaseR, fDestAngle, fSpd * 4.0f);
is that right?
Thanks for your help, as always