The big TimeDelta headache

For questions about using Classic.

Post » Fri Oct 24, 2008 10:05 am

[quote="Arcticus":2qc1rykr]I don't know if this is any help, but if i'm ever in the situation where i need a little more accuracy in my movement engines, i make a little 'for' loop

Make a global varible called like, 'MovementAccuracy'
change the sampling to linear
And then at the start of layout (or change initial value) set it to the amount of accuracy you want
I usually set it to around 50, the higher it is, the more accurate you will get, although i'm not sure the cpu load it would have if you made it too high
Then do something like this

when right arrow is down
--for "Move" from 0 to global('MovementAccuracy')
== Set Player.X to Player.X + 200 * (timedelta / global('MovementAccuracy')

(the -- indicates a subevent)
(the == indicates an action)

Basically, the 'logic' runs 50 times per tick (or however many you set your global to) as opposed to once per tick, but you still get to use timedelta and use all your cool motion blur and timescaling stuff!
Apply that to your jumping code or moving code or whatever and it's pretty much pixel perfect
I had an example running at 1 fps that only went one pixel out

Or another method i suppose would be having variables like: "JumpStart" and "JumpMaxHeight" and make it so when the player jumps, the jumpstart records the Y value at 'ground level' and set jumpmaxheight to the jumpstart minus however high you want him to jump.
Then if the difference between the player's Y and jumpstart goes beyond jumpmaxheight, manually set the distance and code in the falling. Although i suppose this method would be a little harder if you weren't using a custom movement, and for REALLY low frame rates it might still require the use of that 'For' loop i just mentioned
I hope i made myself clear[/quote:2qc1rykr]

This... actually seems like a potentially good idea. Granted what you said is not far off from how my engine already works, but it makes me think of things a little differently. The implementation I'm now thinking would be say.. use time delta to figure out how many times to run accuracy essential logic and run it X amount of times. I used to figure this wasn't reasonably possible, but if I'm looping the essential logic say 5-10 times normally, adding or subtracting a few reps should keep things in speed.

The problem for me though is still keeping animation properly in since (which operates with delta-time in mind). It's essential for me that animations line up exactly when they should. Any way to get around this would either involve... making my own animation engine from scratch or........ Bugging Ashley to implement a feature only I'll ever use (Something like telling an animation to advance a 'tick frame' instead of a whole frame of animation). Which is a waste of time. Alas. But for our opening poster, maybe this would work!

Anyways, Ashley.

http://allefant.sourceforge.net/wordpress/vsync

Nothing professional here and I'm sure a lot of stuff you already know. Still, it talks about the whole logic vs update thing I talk about. So at least my thoughts are somewhere on base and not some unique fabrication. Again for professional examples, I think they'll be hard to find simply because, well.. Again, theres not a lot of professional level 2d computer games these days. Though as I read around, I see a lot of this stuff mentioned, though nothing solid enough to further waste your time with.

I also saw some stuff mentioned somewhere about netplay like I said earlier about FPSs and how relying on delta time for a networked game could be a bit weird. I don't know how accurate that statement is, it's just what I read from some random internet person. :P

Edit: Actually now that I think of it, adding a feature like the one I'd need wouldn't be that hard I don't think and might be more generally useful. Just a command like "Random Object: Advance Animation X ticks". all the user would have to do to do what I want is set animation speed to 0 for whatever objects they want to control. Not saying you should do this, but I think it might be a valid option. I'm just brain storm thought.

Also: I'm curious how collision detection works. If I were to manually run logic several times a frame, would collisions work properly on the 'inbetween' updates, or do collisions only take into account the final or previous displayed state?
B
12
S
4
G
4
Posts: 238
Reputation: 2,426

Post » Fri Oct 24, 2008 11:22 am

i'm pretty sure collisions update between frames

so with your animations, you want to basically control when the animation goes to the next frame?
I haven't worked much with animations on construct yet cause they seem kinda broken and the features i need aren't really in it (yet?), but would you not be able to say, always set animation frame to some variable, and when you want it to progress, just add one to the variable?
I could have interpreted you wrong though
Also i realise it's quite a roundabout way of doing things, a 'next frame' feature would be handy in some cases i expect
B
3
S
2
G
5
Posts: 351
Reputation: 2,377

Post » Fri Oct 24, 2008 4:28 pm

[quote="Arcticus":1r65uhl8]i'm pretty sure collisions update between frames[/quote:1r65uhl8]

They do. I posted a test for detectorless hitboxes somewhere around here that changes the animation of a sprite to it's hitbox, runs an overlap check, then changes back to the original animation in the same tick.
Moderator
B
5
S
2
G
6
Posts: 4,348
Reputation: 10,971

Post » Fri Oct 24, 2008 7:08 pm

Awesome to know, thanks guys. I figured that'd be the case, so thats good to know.

Anyways, as for the animation, a counter wouldn't really work. The problem here is that i need to be able to control how many ticks a particular animation stays out. Currently all my animations are set to speed 60 so I can exactly control how long everything lasts on the screen. If this was a simplier game (IWBTG), I could just use dead/repeat frames, but considering how many frames of animation I'll need in my current game, this just isn't sensible. To adequately do my own animation system I would have to have a string for every animation (or maybe just use an array) that lists all the animation data I need. That'd sort of suck. :D

Again though I'm just tossing out ideas and possibilities. I want to hear Ashley's thought on how sensible they are.
B
12
S
4
G
4
Posts: 238
Reputation: 2,426

Post » Sat Oct 25, 2008 6:06 pm

[quote="Arcticus":nb9fjjew]when right arrow is down
--for "Move" from 0 to global('MovementAccuracy')
== Set Player.X to Player.X + 200 * (timedelta / global('MovementAccuracy')[/quote:nb9fjjew]

This is essentially saying:

+ Every tick
+ Repeat 10 times
-> Set X to X + 1

instead of:

+ Every tick
-> Set X to X + 10

In other words it's identical to the simpler one - the only advantage you get is if you do all your collision testing in subevents (collisions are checked on-the-fly when the condition is run). Then the ONLY advantage you get is fast objects are less likely to skip over small obstacles. It won't directly solve any problems with accuracy.

I checked out the link you posted Kayin - it's a very good article, the best I've read on the subject. However, I'm still not convinced by variable rate logic. Firstly, as the article mentions, it could substantially increase CPU usage, especially with a high logic rate. Secondly - and I don't think the article covers this - if logic runs at a rate which is not a multiple of the V-sync rate, then you can get uneven motion. Lets consider easy numbers - VSync = 50Hz and logic = 75fps - for every VSync you alternate between 1 logic update and 2 logic updates. This means between screen updates, objects will move twice as far every refresh. I don't think this would look as smooth as the current system we have. Interpolation is an interesting idea, but I fear it's too difficult to retro-fit it to our current engine (and it would make eventing a custom movement much harder).

Assuming there was some option to run logic at a multiple of the vsync rate (eg. 5x logic runs per vsync), and assuming timers and user input were updated between these separate logic executions, I guess it might be possible to reduce the inaccuracy by reducing the quantisation effect error. I think this could be programmed like Motion Blur, but without the rendering of logic-only runs.

If it's easy to program, I might give it a shot. I don't think I can truly have keyboard input update fairly in logic-only runs, but it might work. It is a very CPU intensive way of solving the problem though - I have no choice but to execute the full event list, not just the motion/timer based ones, in logic-only runs. And I don't know if it'll even help solve the problem significantly. What do you think?

By the way, I've noticed fullscreen games run with very consistent timedelta values - they are usually exactly equal to 1 / vsync rate. It's only windowed games which suffer random timedelta variations, probably because Windows treats fullscreen apps with a higher priority.
Scirra Founder
B
359
S
214
G
72
Posts: 22,952
Reputation: 178,580

Post » Sat Oct 25, 2008 8:50 pm

[quote="Ashley":1u9nnqgi]
I checked out the link you posted Kayin - it's a very good article, the best I've read on the subject. However, I'm still not convinced by variable rate logic. Firstly, as the article mentions, it could substantially increase CPU usage, especially with a high logic rate. Secondly - and I don't think the article covers this - if logic runs at a rate which is not a multiple of the V-sync rate, then you can get uneven motion. Lets consider easy numbers - VSync = 50Hz and logic = 75fps - for every VSync you alternate between 1 logic update and 2 logic updates. This means between screen updates, objects will move twice as far every refresh. I don't think this would look as smooth as the current system we have. Interpolation is an interesting idea, but I fear it's too difficult to retro-fit it to our current engine (and it would make eventing a custom movement much harder).
[/quote:1u9nnqgi]

Well glad it was a good article and a good read! Yeah, which seems why a much higher logic rate would be better -- with obvious potential problems. It'd be nice if there was a good way to tell how much cpu the logic in comparison to the display. Just for theory sake. But anyways a lot of this will depend on how easily you can program it and have it work appropriately. What issues would this have with custom movement engines, for example? is it a more technical issue?

Anyways, as I think about it,the best way to handle this might be on the event list side. Say a loop-esque feature that times an event for x times a second. Basically, updating the chosen logic at the rate desired (sort of like setting it on the timing but it will interpolate how many times it has to run it per tick). I'd set this like a function. Like

-On Independant Logic "hurfdurf"
--Game jumping/moving logic.

and then like

-on start of frame
-- set Independant Logic Rate "hurfdurf" 100 cycles per second

This might even be doable with stuff already provided. The only problem involved in this is that animations would likely not sync up appropriately and we would need some way to control that. I personally like setting all animation speeds to zero and manually forcing 'tick' updates on the animations, but thats just seems like what would be the easiest answer from my view.

Assuming there was some option to run logic at a multiple of the vsync rate (eg. 5x logic runs per vsync), and assuming timers and user input were updated between these separate logic executions, I guess it might be possible to reduce the inaccuracy by reducing the quantisation effect error. I think this could be programmed like Motion Blur, but without the rendering of logic-only runs.

[quote:1u9nnqgi]
If it's easy to program, I might give it a shot. I don't think I can truly have keyboard input update fairly in logic-only runs, but it might work. It is a very CPU intensive way of solving the problem though - I have no choice but to execute the full event list, not just the motion/timer based ones, in logic-only runs. And I don't know if it'll even help solve the problem significantly. What do you think?

By the way, I've noticed fullscreen games run with very consistent timedelta values - they are usually exactly equal to 1 / vsync rate. It's only windowed games which suffer random timedelta variations, probably because Windows treats fullscreen apps with a higher priority.[/quote:1u9nnqgi]

I thank you for considering this as always and hopefully we can come up with a solution to the problem some of have. I don't see how this wouldn't solve the problem -- more the issue I;'d more think is if it'd cause more problems (by being stuttery or something). Maybe I'll take a stab at making an engine that does this with the available features as a proof of concept (ignoring animation issues).
B
12
S
4
G
4
Posts: 238
Reputation: 2,426

Post » Sun Oct 26, 2008 4:30 am

I realise my little 'for' loop accuracy thing doesn't actually increase accuracy, it does however lessen the jump of timedelta based custom movments at low fps
B
3
S
2
G
5
Posts: 351
Reputation: 2,377

Post » Sat Nov 01, 2008 9:29 pm

I did some basic tests of the concept I described. The code is pretty darn simple.

Always: Set Count 1 * (60 * timedelta)
This value basically is equal to how many ticks of logic should have ran at this point. 60 can be whatever you want your logic rate to be.

For the test I used a black box coded to move with the code.

While
-Count Equal Or Greater Than 1

And then had the event as

Subtract 1 from Count
Set Position X (X + whatever)

I tested it alone and then injected it in my game so I could test it under stress. The results were pretty great -- it seemed no less attractive than the normal, low FPS movement yet, if it were a more complex engine, would be far more accurate in terms of pixel exact movement (probably at an impercievable cost of time accuracy). I'm thinking this could be programmed to use the loop function but I'm not sure how that handles I take it it runs each loop event once then repeats instead of going, say.. "loop event A 3 times. Loop even B 3 times. Loop event C 3 times."? I don't have the time to test right now.

Still, construct at low FPS seems extra stupid ugly for some reason. Maybe it's just my code in general? Who knows, but heres my thought. My idea of time scale smoothing for frame rate is a little weird and as I think about what I would do if I was making a game from the ground up would more involve not letting the FPS jump wildly in the first place -- Basically even out in frame updates instead of on a timescale basis. Would that sound more like a reasonable developers decision, Ashley.

With this process I'm still sort of concerned about properly linking animations to the logic refresh rate, but as I think of it it might not be a problem (though as I'm using animations as almost a timing function, I'm a little anal about this -- but I think I'm in the VAST minority). Thoughts on this? I could upload examples but it seems pointless as it's such an easy little setup. I might try plugging my entire engine in like this at some point and testing that to see how much the logic eats away at the framerate.

Thoughts anyone? I'm particularly curious as to what you think, Ashley, especially because this direction would mean less work for you -- but I'm not sure if it'/s the right one. It seems good and intelligent to me, but I'm a fake programmer. :)
B
12
S
4
G
4
Posts: 238
Reputation: 2,426

Post » Sun Nov 02, 2008 2:51 am

Things get more interesting now. I tested it and converted the base chunk of my engine. It works well. It also gives me a way to control the time delta 'shimmie' that seems to happen a lower framerates.

Currently my engine is tooled to run at 60 ticks. At runs pretty okay at lower FPSs but gives the appearance of relatively lower frame rates Not very bad, but a notable problem with a solution. I'll, at one point, have to try and retool the engine to a higher logic rate -- not a big deal, just tweaking values. Like that, it should be good even at low frame rates. I was able to run the logic at -1000- cycles and the frame rate was still pretty good. I think 100 or 120 cycles will be easily handleable even with a relatively complex engine like mine. Zipping around at insane speeds with pixel perfect accuracy? Priceless.

Anyways if you look at the code,you'll notice a logic limiter right now. It's set to 2,meaning logic can only update a max of 2 times.This nearly kills all the positional jerkiness under lower FPSs (30-45). What was weird is while watching the logic counter tick up, I'd occaisonally see numbers like 7 or 9 while running primarily at the 45 fps range. Really at 45 there should never be a number larger than 2 -- maybe 3 somehow? But yeah. Thats ODD, but it's not an issue now. if I increase the logic rate (which I believe I wll), I can up this probably to 5 or something and still keep things hella smooth.

I think this is the most productive path to follow for us super anal developers and again, I'd like to hear Ashley's opinion on this all to make sure it's a safe course ot proceed down.

http://kayin.pyoko.org/logicspeed.cap

This is the example. Note that not all of the engine is converted, just the very minimal (jumping,gravity and horizontal movement), so theres some weirdness with some of the stuff like dashing and air dashing. All the relevant core logic stuff is the first view events. As you can see, this is a very simple to implement and even still benefits from things like timescale!
B
12
S
4
G
4
Posts: 238
Reputation: 2,426

Post » Sun Nov 02, 2008 11:00 pm

I've thought about this idea and it's interesting... one thing I'm sure of, is that the logic rate should never be less than the display rate. If this happens, eventually you end up drawing the screen with no logic runs in between, which results in an uneven display. Your example uses 60 - my refresh rate is 75 Hz so this would be happening for me. I noticed the scrolling seemed to be jittering side to side constantly, maybe that's a side effect of that.

Next problem is that you might get uneven logic runs - alternating 1 and 2 logic runs per display means you'd move twice as far in one display than the next - but I guess we can live with that, since everything is pixel perfect precision. V-synced display is not perfect in windowed mode - it's much more reliable in fullscreen - so V-synced windowed games tend to 'drop' a frame (ie. miss a V-sync) every now and then. This could explain the logic running a lot to catch up when the next tick runs.

So it's a nice way to go about coding things - the only catch is if this is to be built in to the runtime, it can't distinguish movement code so would have to run the entire event list every logic execution. This might be OK I guess, but it might also use a lot of unecessary CPU. I would prefer to avoid using a trigger like 'On logic execution', because it won't integrate nicely with other features (ie. in theory it should be able to easily switch between a timedelta'd platform engine to a fixed rate logic platform engine without recoding the whole thing). If a 'fixed rate logic' mode was enabled, combined with 'override timedelta' (so timedelta is constant), this would achieve a similar thing, but at the expense of running the entire event list.

Your engine looks pretty good at the moment - you might find it more convenient to simply put all the movement code as a subevent to a single trigger (saves repeating the condition all the time). Also, the Function object does what you're trying to do with fastloops (a one-run fastloop is effectively a function). And as mentioned, you probably want to boost this to at least 120fps logic.

So really for a pixel-perfect engine which is as efficient as possible, you've hit on the right way to do it already! It can be done entirely with events. Do you think it should still be a built in feature, at the expense of running the entire event list?
Scirra Founder
B
359
S
214
G
72
Posts: 22,952
Reputation: 178,580

PreviousNext

Return to Help & Support using Construct Classic

Who is online

Users browsing this forum: No registered users and 5 guests