GMS 2.3+ how to implement delta time on a large scale project?

saffeine

Member
i'm in the process of making a game with animations and frame data, but i plan on sending that over a network at some point down the line for a co-op mode ( only 2-4 players, nothing huge ).
it's not a fighting game per-se, it's a hack n slash, but obviously there's an overlap as far as hitboxes / hurtboxes / typical fighter data goes.
i've played around with networking before, but that was on smaller projects that didn't depend too much on whether or not the clients were delayed ( to an extent ), so i'm familiar enough with that i think.
i understand that networking runs best on a fixed timestep / operating on delta timing rather than relying solely on gamemaker's game speed and system performance to stay on beat.
currently i'm building it around a single function call that iterates through all appropriate systems and updates them as necessary, but what would be the best way to separate that from the fps / gamemaker's game speed?

i know i can use delta_time, divide it by 1,000,000 to get a factor to multiply other values by, such as movement speed, but what about all of the steps in between?
as far as i can figure, the best way to do it would probably be to track the game step and increment that by ( 1 * dt ), then run the game loop x amount of times, but i'd hate to commit to that just to find out it doesn't work later.
does anybody else have any experience with this, or can anyone confirm / deny that i have the right idea? are there any downsides to this approach i should be aware of? any major concerns that might pop up later?

update + alternative question: i'm realising that looping the game x amount of times according to delta is probably unnecessary, but i still don't really know how i would go about calculating hitboxes and such if i don't. normally i would probably consider just checking active hitboxes per frame and comparing them to a unit's bbox, but if there's a lag spike at any point while using delta time, how can i make sure a hitbox comes out at the same position consistently, at the correct time, between the last and current frame?

all feedback and suggestions are greatly appreciated, in the meantime, i'll be looking up more resources to try and learn from.
 
Last edited:

Yal

šŸ§ *penguin noises*
GMC Elder
When you have a distributed system, things will go out of sync sooner or later, so it's better to have a system that lets you resynchronize things at regular intervals than trying to get them to always move in the same pace (e.g. every 5-10 seconds, have the master send the slaves a list of where all the players are and what enemies are alive). You don't need to simulate everything if you just send the status directly, and if things being in the exact right position is important this is one of the ways you can ensure that.
 

saffeine

Member
When you have a distributed system, things will go out of sync sooner or later, so it's better to have a system that lets you resynchronize things at regular intervals than trying to get them to always move in the same pace (e.g. every 5-10 seconds, have the master send the slaves a list of where all the players are and what enemies are alive). You don't need to simulate everything if you just send the status directly, and if things being in the exact right position is important this is one of the ways you can ensure that.
that's all well and good, and i do plan to have things resynchronise every couple of seconds, but what about local delta timing to keep things feeling smooth for the player?

if a machine is running slow and i'm trying to use delta timing to make sure the animations / movements are still advancing at the right speed ( say a walk speed of 16 pixels per real world second ), how can i be sure that in an extreme case where the animation frame might skip from 17 to 21, an event that's supposed to happen on the 20th frame still happens? i think my biggest worry is that if a hitbox is only supposed to last a single frame, it'll be lost if the frames aren't accounted for, or it'll be in the wrong place on the wrong game update if i handle it badly.

is there an efficient way to deal with this, or am i just worrying too much about something that won't end up being a big deal anyway? i think i'd be fine with just letting it be if i was confident that there weren't going to be any edge cases where the game just breaks or feels bad because things aren't appearing to move at the same speed during fps drops. of course i don't even know for sure that those edge cases exist, but i'm trying to prepare for the worst.

maybe i'm just being too paranoid over something incredibly minor.
 

GMWolf

aka fel666
If you want things to be stable and consistent, then looping N times per step is the only way.

Code:
timeAcc += delta_time;
while(timeAcc >= fixed_dt)
{
 //Update the entire world
 timeAcc -= fixed_dt;
}
That's if you want absolute stability.
The advantage of being able to step the entire world is that it becomes much easier to implement things like rollback reconciliation later on (if needed, not recommended because of complexity and cost in GameMaker).
It's hard to implement in GM because you have no control over the game loop. (I blame GM for being very poorly designed in that respect: step loop and draw loops should be separate)

If you don't need perfect stability, then you can just multiply your values by dt.
So X += dt * dx;
That's what most games do and easier to implement in GM
 

saffeine

Member
If you want things to be stable and consistent, then looping N times per step is the only way.

Code:
timeAcc += delta_time;
while(timeAcc >= fixed_dt)
{
//Update the entire world
timeAcc -= fixed_dt;
}
That's if you want absolute stability.
The advantage of being able to step the entire world is that it becomes much easier to implement things like rollback reconciliation later on (if needed, not recommended because of complexity and cost in GameMaker).


If you don't need perfect stability, then you can just multiply your values by dt.
So X += dt * dx;
That's what most games do and easier to implement in GM +=

that's reassuring. i feel like i might need absolute stability for certain things such as frame-dependent hitboxes, and hearing that games actually do operate like that makes me feel better about considering it.
in my head i was under the impression that looping was going to just result in a feedback loop of worsening performance on lower-end systems, which is still entirely possible.

for example:
- the current frame is 0, the real frame ( delta-timed ) is 0.
- the current frame is delayed slightly, and the real frame advances maybe 3 steps.
- the current frame attempts to catch up by looping 3 times, and in that time, with slow processing, the real frame advances a further 7 steps.
- the current frame attempts to catch up here by looping 7 times, delaying it even further with slow processing, and the real frame advances another 13 steps from there.
- by then you get the idea, and that's what i was caught up thinking about while asking the question.

i suppose it's still a possibility, but if it's been tried and tested before, i might as well give it a shot and hope for the best.
worst case, i still have the update loop operating on a variable basis, so i can just set the value to 1 and allow it to do its thing while i work out the kinks.

i'm definitely thinking about this way too much for what little progress i've made up to this point, but i'm assuring myself it'll be easier to work out now than to compensate for and rewrite later.
 

GMWolf

aka fel666
It 100% can result in it looping forever.
The solution then is to cap the maximum dt to what the pc can handle, or just crash and burn.

Many games, including AAA games Will just got the obvious dt rout.
The looping dt is probably less common.

I don't know how well it ends up working in GM. In C/c++ I'd say it's fine because "computers are fast".
But GML code is over 100Ɨ slower.

Just pick a sensible fixed time step, like 1/120 or 1/60, nothing too high.
 
Top