Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SFML and Game time  (Read 13258 times)

0 Members and 1 Guest are viewing this topic.

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
SFML and Game time
« on: May 26, 2016, 04:09:14 pm »
Sorry if this post is a bit vague, it has been very difficult to wrap my head around everything involved.

For starters:
Language - VB.NET...yes, I already know -_-
SFML - Posting these questions here because the graphics engine plays a key part in my maths.
Farseer - Unable to locate examples that will translate into vb.net
Box2d - I found 1 C# example that I was able to get translated, but am unable to grasp how to set the objects sizes and positions...let's pretend that I don't program as a 9-5, and/or am an idiot.

Okay, with that out of the way I have been transitioning a top down game engine to be able to support 2D side-scrolling.  To test I have been simply trying to get a ball to have visually accurate physics in a testbed application.  It didn't take very long to determine that I would need to incorporate a physics engine for the simple purpose of providing (any) objects realistic physics...and since I have been unable to locate a solid example in vb.net, and trying to get the above engines to work properly is beyond the scope of my understanding, I am simplifying things and building my own engine.

Change in Time, or Delta Time, is one thing that has come up in just about every physics equation that I would have to use to calculate falling/collision/velocity.  The way I am using SFML in my application has a large effect on the time that I need to calculate:

Private Sub InitializeEngine()

        ' Request a 24-bits depth bufer when creating the window.
        Dim contextSettings As New ContextSettings()
        contextSettings.DepthBits = 24

        ' Create main window.
        _testbedWindow = New RenderWindow(New VideoMode(800, 600), "SFML Graphic Controls Testbed Application.", Styles.Default, contextSettings)
        _testbedWindow.SetVerticalSyncEnabled(True)
        _testbedWindow.SetFramerateLimit(60)

    End Sub
 

I understand what SetFramerateLimit does, but when it is turned off it seems pointless since SetVerticalSyncEnabled keeps my FPS around ~60.  However,  just found out that is most likely due to the refresh rate of my monitor, and someone with a 75hertz refresh rate would have a higher FPS without the limit.  Perfect, and I understand it...

Now in my game loop I am calling this every loop:
        ' Reset to keep all timers in sync.
        _currentTick = Environment.TickCount

        ' Counts time every loop, then updates the FPS every second.
        If _currentTick - _timeCount >= 1000 Then
            _fps = _fpsCount
            _fpsCount = 0
            _timeCount = _currentTick
        Else
            _fpsCount += 1
        End If
 

Great...every loop add 1 to the _fpsCount until it reaches 1000 ticks, then update my _fps value that will display on my screen...Check!

In order to achieve realistic physics, I have to get the Change in Time between each game loop.  Since I am already returning the Environment.TickCount every loop, what is the most practical, and most accurate, method to produce the time between the frames?  I could have a Delta_Time variable setup, but I honestly have no clue using SFML the way currently am to return a value to apply to it, that can be applied to the physics equations I have found with my google-foo.

Please not I'm not looking for code, just the logic behind how this is supposed to work properly.  If there is anything that I have overlooked, please let me know.

AlexxanderX

  • Full Member
  • ***
  • Posts: 128
    • View Profile
    • AlexanderX
Re: SFML and Game time
« Reply #1 on: May 26, 2016, 07:44:37 pm »
Maybe this will help Fix Your Timestep!.
Here you can find my blog and tutorials about SFML - http://alexanderx.net/ (died...) - http://web.archive.org/web/20160110002847/http://alexanderx.net/

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: SFML and Game time
« Reply #2 on: May 26, 2016, 07:48:22 pm »
Maybe this will help Fix Your Timestep!.

I have that exact document up in my browser right now LOL

But I was unclear how applicable it would be considering how I can set the max FPS, and the Vsync, both have an effect on the speed of the game.  I did not know if other people use this, or a different method using SFML to correctly adjust TimeStep in their games.

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: SFML and Game time
« Reply #3 on: May 26, 2016, 08:30:37 pm »
Well for one, you don't want both a framerate limit and Vsync.

Two, having a fixed timestep allows for your game to run flexibly, while more-or-less playing the same on different quality hardware. Lower FPS on low-end machines, and higher FPS on high-end machines. But, due to the fixed timestep, the game will still run as desired (potentially except for machines below your minimum required specs).

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: SFML and Game time
« Reply #4 on: May 26, 2016, 08:58:28 pm »
Well for one, you don't want both a framerate limit and Vsync.

Two, having a fixed timestep allows for your game to run flexibly, while more-or-less playing the same on different quality hardware. Lower FPS on low-end machines, and higher FPS on high-end machines. But, due to the fixed timestep, the game will still run as desired (potentially except for machines below your minimum required specs).

Okay, would it be advised to turn off the vsync and just have a max FPS set?

Hapax

  • Hero Member
  • *****
  • Posts: 3346
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: SFML and Game time
« Reply #5 on: May 27, 2016, 12:50:12 am »
Okay, would it be advised to turn off the vsync and just have a max FPS set?
This is subject to opinion and taste.

The guy who wrote Fix Your Timestep says somewhere that everyone should just use vertical sync. This, however, has a few drawbacks. The main one, of course, is that vertical sync is dependant on the graphics driver. SFML simply requests that it should be on (or off) and the driver decides whether or not it should listen. Most drivers have options to turn on, off, or let the application decide. If this is not set to letting the application decide, there's nothing the application can do.

Limiting the frame rate also has its drawbacks, of course. The actual length of time for each frame is not consistent so framerates can still fluxuate. Limiting the frame rate is useful to avoid hogging the CPU when it's not actually needed; this, for one, can help reduce the power consumption, which is something to consider if you're building for battery-powered devices. However, the frame rate just being limited doesn't help with the possibility of visual "tearing", which can only really be fixed properly by vertical synchronisation.

So, frame rate limiting is done by the program and vertical sync is asked to be done by the graphics driver. You can use either or neither but, whatever happens, never use both.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: SFML and Game time
« Reply #6 on: May 27, 2016, 08:04:28 am »
The option I'm partial towards is letting the player choose. Have a V-sync option, and a frame rate limit option. I've seen several AAA games do this. So, by default, for example, you simply have neither enabled (or whatever you think is best). Then players can choose as they like.

Just make sure to make them mutually-exclusive!

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: SFML and Game time
« Reply #7 on: May 27, 2016, 01:49:39 pm »
Thanks guys!

I decided to change getting the time from the Environmental.TickCount to using SFML's clock class.  Using this I am looping through until the time between passes hits an interval amount (16ms - for 60hz; 20ms - for 50hz), so I can have either fps limit or vsync on, or neither and still produce a relative rate to pass through for DeltaTime (16ms).

I'm sending 1/dt through and getting 0.0625ms consistently, which now gives me something to work with to calculate a falling object and implementing gravity.  However, I am not quite understanding the values for the monitor refresh rates (16 or 20), and why they seem to be arbitrary values.

'// 16 for 60hz; 20 for 50hz
interval As Double = 16
 

        _previousTime = _currentTime

        Do
            _currentTime = clk.ElapsedTime.AsMilliseconds()
        Loop While (_currentTime - _previousTime) < interval

        _elapsedTime = _currentTime - _previousTime

        _deltaTime = (1 / _elapsedTime)
 

While I have no idea why the specific interval value, I got the idea for looping through like this from Hapax's Kairos project.  I even tried to make that a dll to use, but I failed horribly because I suck at c++, LOL.  I'm gonna have to crack down and see if there is any way to do a class similar to that so it would be .net compatible (unless it already is and I just am clueless on how to use it) ;)

Hapax

  • Hero Member
  • *****
  • Posts: 3346
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: SFML and Game time
« Reply #8 on: May 28, 2016, 02:24:37 pm »
The Timestep classes (Timestep and Timestep Lite) in Kairos are designed to simplify the fixed timestep method described in Fix Your Timestep.

Your code, however, seems to be just looping until a certain period of time has occurred. This is blocking and can slow down your application (it's also very similar to setFrameLimit).
This means that each frame will be at least a certain amount (it can be greater than or equal to "interval") but never reliably exact. Deltatime in this case is not consistent. If this loop is interrupted (say, the window is moved) and when it returns the time is (for example) interval * 100 past the previous time, elapsed would be interval * 100 and delta time would be 100 times smaller.

The idea behind the method(s) in Fix Your Timestep is to always process the same timestep each time. If the amount of time past isn't enough ("< interval" in your case), don't update any logic, physics etc.. If the time past is higher than interval, process just that interval and remove it from the amount of time (accumulation is a way of keeping of track of this). The loop is for cases where the amount of time past is greater than two times that desired interval/delta time. It would process each interval in the loop until there isn't enough time to process a single interval. Then, it would exit the loop and update the window etc..

Fix Your Timestep has the pseudo code already for you to be able to implement it yourself. Just remember that "integrate" in this case means "update your game's logic and physics".
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: SFML and Game time
« Reply #9 on: May 28, 2016, 04:46:50 pm »
I really appreciate you taking the time to explain this stuff better than what I am understanding it.

Okay, so essentially I am doing everything wrong in order to have a consistent game loop.  Current here is my loop:

        While (myRenderWindow.IsOpen)
            CalculateTimers()
            SetupScreen()
            ApplyPhysics()
            DrawEntities()
            DrawInfo()
            PresentScreen()
        End While
        DestroyGame()
 

Instead I should be moving all of my objects (ApplyPhysics) when I am calculating the timers?

All of this is really confusing.  I tried porting over the RK4 integration from his website.  The term "State" used in it is a Structure that holds a Position and Velocity definition.  However, the balls Position and Velocity both have an (x, y) coordinate value.  Since gravity is constantly applied to the Ball, am I only supposed to be calculating the Position.Y and Velocity.Y?

Dim alpha As Double = accumulator / dt
Dim state As State= currentState * alpha + previousState * (1.0 - alpha)
render(state)
 

I don't know about C++, but in VB there is no way to simply add [State(x, v) = currState(x. v) * alpha ...], and instead I would have to add:

[State.x = currState.x * alpha ...]
[State.v = currState.v * alpha ...]

Which is fine, but what does "render(state)" mean?  Is that simply just displaying everything I have moved and drawn to the screen, or have I completely missed the idea and should just take up stamp collecting for a hobby? LOL

Hapax

  • Hero Member
  • *****
  • Posts: 3346
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: SFML and Game time
« Reply #10 on: May 28, 2016, 08:36:08 pm »
The code used in that article is rather pseudo.
"State" is, simply, the state of everything at that time. It is every variable used for everything in the physics and logic.
Now, with that said, you don't necessarily use everything.

There is no real reason to not apply both components though:
state.position = currentState.position * alpha
state here would be the final state of everything for the frame you are preparing for and currentState would be the state of everything at the previous frame. This sounds overly complicated but it's only needed if you are doing the very final step in that article (the final touch). I'd leave that for now until you're more comfortable with the timing.

Some pseudo code for an implementation of fixed timestep:
deltaTime = 0.1 seconds
while (windowIsOpen)
{
    currentTime = clock.currentTime
    timeToProcess = timeToProcess + currentTime - previousTime
    previousTime = currentTime

    while (timeToProcess >= deltaTime)
    {
        applyLogicAndPhysics()
        timeToProcess = timeToProcess - deltaTime
    }

    prepareDisplay()
    drawDisplay()
}
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: SFML and Game time
« Reply #11 on: May 28, 2016, 11:44:14 pm »
No joke, but I literally almost had that exact same code after downloading the actual C++ sources from the tutorial.  It took me quite a while to figure out why the movements were so sudden, meaning I would press a direction and the ball was on the other side of the screen.

I had to look at Kairos Timestep example to figure out I had to multiply by the delta time.  For some reason everything I had for RK4 movement would not work, so I just implemented it inline and now it is working:

                Dim k1 As Double, k2 As Double, k3 As Double, k4 As Double
                '4th order
                k1 = deltaTime * dydx(Ball.Velocity.Y, Ball.Position.Y)
                k2 = deltaTime * dydx(Ball.Velocity.Y + deltaTime / 2, Ball.Position.Y + k1 / 2)
                k3 = deltaTime * dydx(Ball.Velocity.Y + deltaTime / 2, Ball.Position.Y + k2 / 2)
                k4 = deltaTime * dydx(Ball.Velocity.Y + deltaTime, Ball.Position.Y + k3)
                Ball.Position.Y += (1 / 6) * (k1 + (2 * k2) + (2 * k3) + k4)
 

That is probably wrong though, but I will worry with it later.  Thanks again for all the help man!

Hapax

  • Hero Member
  • *****
  • Posts: 3346
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: SFML and Game time
« Reply #12 on: May 29, 2016, 12:48:21 am »
You don't technically have to multiply by the delta time. Since the delta time is constant, you can just use lower values. However, if it's at all regular-time based (for physics for example), it would be easier to use easier to understand values along with multiplying with dt. This also is required if you ever need to change the delta time but that should not be done as much as possible.

I haven't implemented RK4 myself so I can't really help. However, looking at the Gaffer on Games explanation, it looks like there is a lot more code required.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: SFML and Game time
« Reply #13 on: May 29, 2016, 01:22:00 am »
Yeah, this was all my original code for the RK4 method that I ninja'd from the C++ code examples.  Before I followed your instructions for fixing my timestep I had this working, but since I implemented the fix I am going back over all the code, because there is a lot that is being left out of the calculations (momentum, friction).

More basic equations can be found here Runge Kutta 4...it took me forever to find something that was easy to understand, and not have all the complicated symbols.

One thing I do not understand about all of this is why isn't any of the (x) values being calculated?  Because all this is totally new to me, and I suck at differential equations, this has been a struggle to understand.

Regardless, since this is VB, it is about as close to pseudo code as you can get ;)

    Private Structure State
        Dim pos As Single ' position
        Dim vel As Single ' velocity
    End Structure

    Private Structure Derivative
        Dim dx As Single ' dx/dt = velocity
        Dim dv As Single ' dv/dt = acceleration
    End Structure

    Private Function acceleration(ByVal state As State, ByVal t As Single) As Single
        Const k As Single = 10
        Const b As Single = 1
        Return -(k * state.pos - b * state.vel)
    End Function

    Private Function evaluate(ByVal initial As State, ByVal t As Single) As Derivative
        Dim output As New Derivative()
        output.dx = initial.vel
        output.dv = acceleration(initial, t)
        Return output
    End Function

    Private Function evaluate(ByVal initial As State, ByVal t As Single, ByVal dt As Single, ByVal d As Derivative) As Derivative
        Dim state As New State()
        state.pos = initial.pos + d.dx * dt
        state.vel = initial.vel + d.dv * dt
        Dim output As New Derivative()
        output.dx = state.vel
        output.dv = acceleration(state, t + dt)
        Return output
    End Function

    Private Sub integrate(ByVal state As State, ByVal t As Single, ByVal dt As Single)
        Dim a As Derivative = evaluate(state, t)
        Dim b As Derivative = evaluate(state, t, dt * 0.5F, a)
        Dim c As Derivative = evaluate(state, t, dt * 0.5F, b)
        Dim d As Derivative = evaluate(state, t, dt, c)

        Dim dxdt As Single = (1.0F / 6.0F) * (a.dx + (2.0F * (b.dx + c.dx)) + d.dx)
        Dim dvdt As Single = (1.0F / 6.0F) * (a.dv + (2.0F * (b.dv + c.dv)) + d.dv)

        state.pos = state.pos + dxdt * dt
        state.vel = state.vel + dvdt * dt
    End Sub
 

Hapax

  • Hero Member
  • *****
  • Posts: 3346
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: SFML and Game time
« Reply #14 on: May 29, 2016, 03:00:33 am »
Which (x) values aren't being calculated? Which (x) values?

VB is not pseudo code; it's very language-specific code :P
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*