movements depend on framerate

Low framerate result in low moving speed and vice versa.

How to reproduce:
1) turn off vsync
2) set frequency to 0 in the clock section (otherwise vsync = false will have no effect)
3) set a fixed physics framerate
3) start a game, any game
4) limit all cpu frequency to 500 MHz, and the framerate will drop significantly which is expected. What is unexpected is that object also moves significantly slower.
5) cancel the cpu freq limits, rerun the game, the framerate can easily exceeds 1000 fps on my device and my little hero becomes a flashman.

Since Orx is not a engine especially dedicated for some kind of console platform, I would say this should be a bug. I looked into the code (glfw, orxPhysics.cpp) and confirmed that the physics updating code intends to achieve fixed time step and I counted that the calling rate of b2world->step is correct, which means this part of code works fine. I also confirmed that orxSystem_GetTime gives correct results and main clock dt is correct. So I honestly got no clue, why would physical movements depend on main framerate?

Comments

  • edited July 2022

    Hi @Tang,

    Movement should not be dependent on framerate, but we need a couple more details before investigating the possibility of a bug:

    • How are you moving your character? Could you post the snippet of code/config that you are using for it?
    • What settings did you use for the main clock? The default ones, which assume the use of VSync to match the refresh rate or custom ones?
    • Was the framerate going under 10FPS at any point?

    Most of the reasons why I asked those questions can be found in our most recent live session about clocks:

  • I think just found out what's actually going on. I was testing something with the "Beginner's guide" and I didn't realize that it uses "orxObject_ApplyImpulse" to apply speed. My apologize, it seems that I went through all the code just trying to find a non-existing bug :s .

    Since the update callback's calling rate is determined by the main framerate and I didn't clamp the speed, "orxObject_ApplyImpulse" can result in different peak speed when the main framerate varies. So I guess the correct way to do this is to to sync the calling rate of "orxObject_ApplyImpulse" with the physics framerate?

    However, there is still one trivial thing that bothers me, that is, if I may ask, why would the framerate still stay in 60 fps when I turned vsync off in config without setting the frequency of the core clock to zero or something that's not 60? what is the purpose of this design?

  • Hi Tang, it's true that the beginner's tutorial doesn't take into account delta time. The guide is just to get familiar with orx in generally. But certainly it's important to use delta time as part of your impulse values as it would vary on machines with different speed, or when a machine stutters.

    I am pretty bad with this stuff usually, I always forget to factor it in.

  • edited July 2022

    @Tang said:
    However, there is still one trivial thing that bothers me, that is, if I may ask, why would the framerate still stay in 60 fps when I turned vsync off in config without setting the frequency of the core clock to zero or something that's not 60? what is the purpose of this design?

    This is explained in details in the video I linked in my previous post. Long story short, the default settings for the core clock is to match the display's refresh rate and use a fixed DT to prevent any micro-stutters.
    This is the result of the combination of two settings, set by default if none are specified manually:

    [core]
    Frequency = display ; The core clock's frequency will match the display rate
    ModifierList = fixed -1 ; The DT will be fixed and match the clock's frequency
    

    If you wanted to remove those constraints, you could simply set the core clock's frequency to 0 (in which case the modifier would also be ignored), or remove both:

    [core]
    Frequency = 0
    ModifierList = fixed 0
    

    You'd then become (almost) entirely time independent (the Render plugin sets a maxed 0.1 modifier on the core clock, but this too can be removed from config), however you'd then be subject to potential visual micro-stutters as the DT will jitter from frame to frame.

  • @iarwain said:

    @Tang said:
    However, there is still one trivial thing that bothers me, that is, if I may ask, why would the framerate still stay in 60 fps when I turned vsync off in config without setting the frequency of the core clock to zero or something that's not 60? what is the purpose of this design?

    This is explained in details in the video I linked in my previous post. Long story short, the default settings for the core clock is to match the display's refresh rate and use a fixed DT to prevent any micro-stutters.
    This is the result of the combination of two settings, set by default if none are specified manually:

    [core]
    Frequency = display ; The core clock's frequency will match the display rate
    ModifierList = fixed -1 ; The DT will be fixed and match the clock's frequency
    

    If you wanted to remove those constraints, you could simply set the core clock's frequency to 0 (in which case the modifier would also be ignored), or remove both:

    [core]
    Frequency = 0
    ModifierList = fixed 0
    

    You'd then become (almost) entirely time independent (the Render plugin sets a maxed 0.1 modifier on the core clock, but this too can be removed from config), however you'd then be subject to potential visual micro-stutters as the DT will jitter from frame to frame.

    Thanks for explaining, I understand that keeping a fixed dt is a sane default, just didn't expect it to still behave the same way after I turned vsync off. Now I fully understand the intention of this :)

  • @sausage said:
    Hi Tang, it's true that the beginner's tutorial doesn't take into account delta time. The guide is just to get familiar with orx in generally. But certainly it's important to use delta time as part of your impulse values as it would vary on machines with different speed, or when a machine stutters.

    I am pretty bad with this stuff usually, I always forget to factor it in.

    Ah, it's just my recklessness, the guide is a good one, which is why I always use it to test things. It's just that orx registers everything to the core clock instead of having an explicit "main loop", and sometimes obvious things can seem less obvious.

  • edited July 2022

    @Tang said:
    Thanks for explaining, I understand that keeping a fixed dt is a sane default, just didn't expect it to still behave the same way after I turned vsync off. Now I fully understand the intention of this :)

    My pleasure! As you've noticed it's not a "one size fits all" kind of solution, unfortunately.
    I was toying with the idea of having a "smarter" fixed DT that would keep a steady value while the real DT is within X % of the intended target and use the actual value otherwise. I still need to experiment with it to see if there's no caveat.
    That would not fix the fact that removing VSync would still result in a framerate limiter with that configuration. The limitation here is that VSync can be switched on/off at runtime while the clock's frequency cannot be redefined at runtime at the moment without deleting and recreating it. I should have a closer look at it to see if it could be a viable option.

  • @iarwain said:

    @Tang said:
    Thanks for explaining, I understand that keeping a fixed dt is a sane default, just didn't expect it to still behave the same way after I turned vsync off. Now I fully understand the intention of this :)

    My pleasure! As you've noticed it's not a "one size fits all" kind of solution, unfortunately.
    I was toying with the idea of having a "smarter" fixed DT that would keep a steady value while the real DT is within X % of the intended target and use the actual value otherwise. I still need to experiment with it to see if there's no caveat.
    That would not fix the fact that removing VSync would still result in a framerate limiter with that configuration. The limitation here is that VSync can be switched on/off at runtime while the clock's frequency cannot be redefined at runtime at the moment without deleting and recreating it. I should have a closer look at it to see if it could be a viable option.

    I'd say that's quite a good idea. These things can actually be very delicate, and conventional ways of keeping a fixed dt can fail at certain circumstances (e. g. "spiral to death" as some call it). What you are trying might improve this even further.

    Anyway, thanks for taking your time to explain the engine.

    BTW, I was actually testing the Lua binding I just created (almost done) when I encountered this. So I'm quite happy that this is just my recklessness :) . Thanks to your hard work I can get a fps almost as high as using native orx (which is far higher than love2d does) :) .

  • Oh congrats for the (almost) completion of the LUA bindings!
    Is that something you'd be willing to share with the community at some point?

  • @iarwain said:
    Oh congrats for the (almost) completion of the LUA bindings!
    Is that something you'd be willing to share with the community at some point?

    Of course! I just still need to add command registration support and figure out a good way to support timers

Sign In or Register to comment.