C2 games and 120hz monitors (*dt problem?)

Discussion and feedback on Construct 2

Post » Sat Jan 24, 2015 4:14 am

Oh, man, yeah, 'every X seconds' should never be used with dt. It uses it internally. So you're actually checking the timer for 60 * dt * dt !

So... The consensus is that the code should be working, assuming that dt has been used correctly everywhere?
B
92
S
31
G
24
Posts: 3,191
Reputation: 32,699

Post » Sat Jan 24, 2015 7:30 am

cacotigon wrote:You should use dt as a means of scaling movement/velocity/vectors/etc. So for example, let's say you have some Sprite1 with CustomMovement, and you want it to move approximately 100 pixels every second. Under an event:
Every Tick (aka every game cycle): Move Sprite1 by dt*100.

This way even if dt fluctuates because of slowdown or because of computers with different refresh rates, you are guaranteed a constant rate of movement.


so in what situations would the "dt*100" provide inconsistencies across different framerates? I use it a lot for adding/subtracting from a variable, for things like cooldowns, is that ok?
B
151
S
75
G
20
Posts: 1,793
Reputation: 22,749

Post » Sat Jan 24, 2015 7:55 am

@alspal

Yeah, using dt to adjust the speed at which variables are modified is great. DT is there so that by saying Add (DT*X) to SomeVar, you can make sure that it is added at a total rate of X per second.

DT returns the elapsed time since the last game tick (basically the last time the event sheet was processed), and it usually hovers around 0.01667 on most 60hz systems (aka 1/60) because Construct 2 uses underlying v-sync related browser timing.

So for example, if you wanted a variable Life to gradually regenerate at 20 points a second. You would say: Add DT*20 to Life. If you test your game on a 60hz refresh rate display: Every game tick, you are adding dt (~0.01667) * 20, or approximately 0.334 life points every tick, after 60 ticks or approximately 1 second, it will have added 20 points to life.

When running same game on 120hz display rate, every game tick, you are adding dt (~0.0083) * 20, or approximately 0.166 life points every tick, and after 120 ticks or approximately 1 second, again it will consistently have added 20 points to life.

So no matter what your frame rate is, dt allows you to maintain consistent value ratios.

Just avoid using dt as a part of a time-dependent condition in an event, so for example, you wouldn't want to have:
Every DT*60 seconds: Add 20 points to Life.

On a 60hz system, dt is 0.01667, so in this case, the statement is roughly equal to: Every 1 second: Add 20 points to life.
But testing on a 120hz system, dt is ~0.0083, so the statement is roughly equal to: Every 0.5 second: Add 20 points to life. Completely different behavior.
B
31
S
7
G
8
Posts: 232
Reputation: 6,274

Post » Sat Jan 24, 2015 10:09 am

Ok, that DT stuff drive me crazy. :(
I really though we should use DT each time we use a time value to secure the game behavior depending on the fps variation. But now I read that's not the case.
Sorry to say that (and I blame nobody) but it's unclear and unintuitive. I just want to make games, not formulas for waiting 1 second depending on the fps, the frequency, the size of the sun and the weather outside.
I have the bad feeling I will have to spend a day, changing all the time events of my game. But right now, I don't even know what to change exactly. Ho bother....I'm lost.

What about every tick event ? Wait action ? We should not use DT too in these cases?
B
72
S
21
G
12
Posts: 314
Reputation: 12,121

Post » Sat Jan 24, 2015 10:52 am

I tried changes on my boss fight. I use DT ONLY for value variations (lerp(x,y,z*dt) or every tick-> value*dt)
It's working the same in 60hz and 120hz.
So is it the right way to do it? Will it work the same when the game slows down too ?
B
72
S
21
G
12
Posts: 314
Reputation: 12,121

Post » Sat Jan 24, 2015 11:22 am

@KaMiZoTo

dt is the duration between two ticks, it is there because events don't occur on a fixed time like every 1/60 seconds.

when you want something to move at a speed of 20 pixels per seconds, you will have to increase its position of 20 pixels each seconds at the end, so at 20*dt pixel each tick to achieve that.

summing up dt every tick into a variable will make said variable increase by 1 each second (unless you have a timescale other than 1 or if the fps goes under 10, those are the two limitations).

the solution?just do the calculation on a simple case with a fixed time and you will know:

at 60 fps, I should be at the same position in one tick than at 120 fps in two ticks (as twice as more ticks will occur).

in your case, you start up at position A, you increase it by 20*dt every tick, lets try on 1/60 of seconds of interval

in one tick (1/60 of seconds) at 60 fps, the next tick it will be A+1/30
at 120 fps (1/60 of seconds, correspond to two ticks), the next tick it will be A+1/60, the tick after that it will be A+1/60+1/60=A+2/60=A+1/30

it is the same result, so you are good.

heck, even more simple: imagine with 10 fps compared to 100 fps (ten times more ticks per seconds), for 1/10 of seconds passed
in one tick at 10 fps, A+20/10=A+2
at 100 fps, in ten ticks: A+20/100+20/100+20/100+20/100+20/100+20/100+20/100+20/100+20/100+20/100 = A+200/100 =A+2

@sqiddster "'every X seconds' should never be used with dt. It uses it internally."

it is easier to understand as "you are acting on a fixed time, so no compensation is needed, every 1 seconds will be true every seconds, regardless of the framerate" (sure it can become false in extreme cases, but those cases are not something you should be designing for).
Game design is all about decomposing the core of your game so it becomes simple instructions.
B
53
S
22
G
18
Posts: 2,122
Reputation: 17,123

Post » Sat Jan 24, 2015 11:51 am

@Aphrodite Thank you. I'm starting to understand.
I'm a little narrow minded sometimes and like when things are simple. That would be great if that dt conversion was automatic...but it's probably utopic!
(I like utopia)
Well, let's check all my events/actions now. :*(

@Aurel If you use DT only for your lerp formulas, this is strange your game goes banana on 120 hz after what I understand from that threat. :/
Perhaps it's related to EVERY TICK -> VALUE changes (with no lerp and no dt)
B
72
S
21
G
12
Posts: 314
Reputation: 12,121

Post » Sat Jan 24, 2015 12:06 pm

"That would be great if that dt conversion was automatic...but it's probably utopic!"

well, it would be hard to know what needs dt and what needs NOT dt (if you move once an object of 200 pixels, dt is not something you might want).

just have an event, compare situation A, and Situation B (the difference being a time between the two), for the same time, you should arrive at the same situation B in both cases in you calculs regardless of the framerate.

btw, just for the "I said it" aspect of that (I know I am boring with that, but now that I can prove it once and for all, I won't let that chance go):

A=lerp(A,B, 120*dt), for 1/30 seconds (2 frames at 60 fps, 4 frames at 120 fps)
at 60 fps, A is first equal to 0, in one frame: A=lerp (0,B, 2)=2B, in two frames A=(2B, B, 2) =0 (if we continued, we would go 2B to 0 to 2B to 0, etc..)
at 120 fps, A is first equal to 0, in one frame: A=lerp(0, B, 1)=B, in two frames, A=lerp(B, B, 1)= B+1*(B-B)=B
in 3 frames, A=lerp(B, B, 1)= B, in 4 frames, A=lerp(B, B, 1)=B (if we continued, it would still be B).

not the same result, so framerate independancy is not there, in short, never use dt in lerp like that, never use lerp like that for that matter, as it is not intended to be used like that!

@Aurel
@KaMiZoTo
Game design is all about decomposing the core of your game so it becomes simple instructions.
B
53
S
22
G
18
Posts: 2,122
Reputation: 17,123

Post » Sat Jan 24, 2015 1:05 pm

Mathematically speaking dt has no relation to specific framerates. A game correctly using dt will work the same (or at least very similarly) at any framerate. Nothing in the C2 engine hard-codes an assumed 60 Hz rate. If your game works twice as fast (or even just differently) at 120 Hz, that strongly suggests you are not using dt when you should be!

I'd point out 'Every X seconds' should not use dt in its parameter. This has exactly the opposite effect of what you want. It is already framerate independent, and adding dt makes it framerate dependent, since:

Every 5 * dt seconds
@ 10 FPS, dt = 0.1, runs every 0.5 seconds
@ 100 FPS, dt = 0.01, runs every 0.05 seconds
It's broken! It now depends on the framerate. On the other hand "Every 5 seconds" runs every 5 seconds at any framerate. So it's simply wrong to use dt in 'Every'.

An easy way to test your game for correct use of dt is to set the timescale to 0.1 and look for anything that is still running at the normal rate. In other words everything should be super-slo-mo, but if you missed dt somewhere then something will be happening way too quickly. It's exactly the same principle that keeps the game running at the same rate at 120 FPS as well (or even higher).

I think A = lerp(A, B, x*dt) is correct, even with A changing every frame. I vaguely remember an alternative from the Construct Classic days of A = lerp(A, B, 1 - x ^ dt), but I can't remember the maths behind it, and some quick experimenting shows that both ways appear to compensate correctly for changes in the framerate although they provide slightly different interpolation curves.
Scirra Founder
B
399
S
236
G
89
Posts: 24,527
Reputation: 195,386

Post » Sat Jan 24, 2015 1:17 pm

@Ashley

"I think A = lerp(A, B, x*dt) is correct, even with A changing every frame. I vaguely remember an alternative from the Construct Classic days of A = lerp(A, B, 1 - x ^ dt), but I can't remember the maths behind it, and some quick experimenting shows that both ways appear to compensate correctly for changes in the framerate although they provide slightly different interpolation curves."

they don't give the same results on the same occuring times, that is enough to say that it is not framerate independant (being "fair enough at the end" is not something I would say correct due to the fact how it is evolving is important in that case, but again using lerp that way is asking for those issues as it is a really weird to do, I am wondering how to do an exponential interpolation to go to 95% of the road from a to be which would be framerate independant completely, will get back if I have the time to do it), did not tried with lerp(A, B, 1- x^dt) so I cannot tell.

EDIT:

Lets imagine
experp(a, b, x), if x =0, returns a, if x =1, returns 0.95b+0.05a, evolution exponential between a and b when x increase linearly from 0 to 1, so you can make x increase of 20*dt for exemple and lock it at x=1, that may work similarly without breaking the framerate independancy.

the function being roughly
a+(1-exp(-3x))*(b-a)

exp(c) being the contant e at the power c (e^c)

if someone can try it on C2 to verify
Last edited by Aphrodite on Sat Jan 24, 2015 1:38 pm, edited 2 times in total.
Game design is all about decomposing the core of your game so it becomes simple instructions.
B
53
S
22
G
18
Posts: 2,122
Reputation: 17,123

PreviousNext

Return to Construct 2 General

Who is online

Users browsing this forum: Niespor and 10 guests