What is the best way to implement tick() method, so i dont have to multiply every movement in game by *tpf ?
You can ignore tpf if you donāt mind your game running at different speeds as frame rate speeds up or slows down⦠else just use tpf. Thereās really no way around it.
Even if you implement a completely separate thread that attempts to always run at a fixed frequency, there will be times where it will lag for one reason or another. Though if you want a fixed time step, thatās the āeasiestā way. You have to manage a whole bunch of threading stuff, though.
Whatās wrong with just using tpf?
Well the most primitive way is to just set the framerate in the settings of the application by code. So you limit the max speed, but it might slowdown based on load, (depending on the gametype this might be the reqired behaviour tho)
In fact my whole server behaves similar, as I prefer a slowed down game to a choppy one.
a very complete article on the subject if you want to understand it all.
I personnaly prefer to use a logic thread that run at fixed rate. This way I only have a constant ātime per frameā and all calculations are based on it. No need to hike the tpf to all layers.
The variable elapsed time between frame (called ātpfā in jMonkey, I never understood why ^^) requires to mutiply things to it and it may become confuse what need to be scaled and what doesnāt need, especially with physic.
Yeah, I do my physics/logic/etc. loops this way on the server also. I still pass a version of tpf⦠itās just fixed. That way I can change the step size without having to rewrite āliterally everythingā.
But when dealing with networking, you are already messing the threading on the client and dealing with the multithreading issues.
To me, in a single player game where the logic is āright thereā⦠for someone at the skill level where they need to ask this question, itās probably 100x easier just to multiply by tpf.
TPF = time per frame
TSLF = time since last frame :chimpanzee_closedlaugh:
TTHPSLF = time that has passed since last frame :chimpanzee_closedlaugh:
Just joking. :chimpanzee_winktongue:
I admire you folks ⦠I wish I knew how to implement a server for a multiplayer game in a clever way (so that I could save the 100 hours (or 200 hours) (or more) to get there)ā¦
Do you know any good tutorials / papers on that topic??
How about this approach?
float timePassed = 0;
public void update(float tpf){
timePassed += tpf;
while(tpf >= 0.05){
tick();
timePassed -= 0.05;
}
}
I know itās not perfect, but in theory it should give you ticks of 0.05 seconds each.
At least 0.05 seconds It seems dangerous to me cause you canāt count on it.
Well many things are not important : the game sjust slows down. But some times, it may lead to very strange behavior. Think about velocity calculations : if the time is slowed, you get a slower speed, but also slower acceleration and deceleration, which may lead to bugs or unexpected results.
What about a damge over time ? should it tick 9 times? of 3 times per seconds? are you sure that the tick count will be the same at every framerate?
A surely fixed frame rate for the game logic is, IMO, a much safer way to code.
Though note: it implies interpolation or prediction to make the visual frame rate sync with your different game thread⦠else you get strange jittering(*). This is not trivial stuff for someone at the level of experience of asking this question in the first place.
(*) could be ugly stuttering doesnāt matter⦠some people want smooth movement, though.
absolutly
No you donāt get any slow down or speedups with his method, I was actually going to suggest exactly the same because it doesnāt involve threads. If the frame rate is slower than 0.05s you get multiple updates in one frame, if its faster you get one every few frames. The only issue is the actual updates of the visual output but you have virtually the same issue when you use a separate thread as Paul hinted.
Thanks for the backup Yeah it just updates multiple times per drawing if the framerate is too small. That can lead to stuttering, but you get that anyway. Also, if you want multiple tick-rates for different parts of your game (I think minecraft does something like that), you can add additional float fields and loops.
And I do see the reason for fixed framerates, especially in games where acceleration is a gameplay factor (I saw a 2D-Game with orbital āphysicsā once where this method was used)
There is one problem in Dinās algorithm though:
If the tick() takes very long, then you will get an eternal slow down.
So you would not just calculate ātime per frameā but need to also cap that to a maximum value.
So if the tick() takes 0.10 seconds then you donāt add the 0.10 seconds but a significantly lower value.
Or you do that cap once the āaccumulated timeā has reached, say, 1 second.
Otherwise a good solution, except for the stuttering that Paul mentionedā¦
Still waiting forā¦
Game Programming Patterns by Nystrom is good. Itās even freely available:
http://gameprogrammingpatterns.com/
Hm⦠his book is more about basic stuff.
Seems not to be specifically about:
Thatās* what I meant by āthat topicā.
Well, anyways, thanks for providing a link to a free book about game coding.
*That and what the others said about their fancy multiplayer serversā¦
@pspeed always has valveās posts at hand
Though I guess you need to be more clear on what you want to achieve since an MMORPG is more complex than a card game though an FPS might be more complex and focus on other things than an MMORPG.
For Example: An MMORPG has to be efficient (because of the MMO part), whereas an FPS has to make heavy use of interpolation and for example every input is captured and delayed (so everything happens in the past).
Well, not yet sure whether itās only for a group of people with FPS-style precision. Or (what I think) an MMO precision with a FPS size group of people (and thus multiple instances on one server).
When Iām at that point (which will take some weeks), I will first look at Monkey Zone, but thatās only a start.
We use that āincrementalā approach in Skylimit Tycoon, and it works well for us.
We have also implemented a game speed enum that indicate what speed the game should run at, with constants to use when multiply for animations, etc. Itās usefull for us since we want to fast forward now and then.
One tick is one minute in our game.
public enum GameSpeed {
PAUSE(0.0f, 0),
NORMAL(1.0f, 1), // 1 minute per second
FAST(1.0f / 8.0f, 2), // 8 minutes per second
VERY_FAST(1.0f / 60.0f, 3); // 60 minutes per second
GameSpeed(final float timePerMinute, final int index) {
this.timePerMinute = timePerMinute;
this.timeModifier = 1.0f / timePerMinute;
this.index = index;
}
private final float timePerMinute;
private final float timeModifier;
private final int index;
/**
* @return the amount of tpf that's required for incrementing a minute
*/
public float getTimePerMinute() {
return this.timePerMinute;
}
/**
* @return the constant to multiply with when skipping time
*/
public float getTimeModifier() {
return this.timeModifier;
}
public int getIndex() {
return index;
}
}
Enum has an āordinalā (0-based index).
If you use that value for anything other than looking up the enum value later then itās best to hard-code some index into the enum⦠else you will break a lot of your code if you ever add an enum in the middle or reorder them. Best not to have these magic side-effects cascade through your code.
ā¦perhaps better still not to use the ordinal() for anything real. (Though it can be very tempting for database storage⦠itās a bad idea.)