0
\$\begingroup\$

by frame skip off i mean that the game should just slow down if the fps drops, just like in terraria, i got this code currently and want to implement it to it:

static class Globals
{
    static public Time dt = new Time();
    static public Vector2f Friction
    {
        get
        {
            return new Vector2f(2 * dt.AsSeconds(), 0);
        }
    }
}

class Player
{
        private void StartMoving(int _direction)
    {
        moving = true;
        direction = _direction;
        heldfor =  1;
        Move(direction);
    }
    public void Move(int _direction)
    {
        if(!moving)
        {
            StartMoving(_direction);
            return;
        }
        if(direction == _direction)
        {
            if(heldfor < heldforlimit) heldfor++; 
            Velocity += new Vector2f(((speed * (heldfor / 10f)) * direction) * Globals.dt.AsSeconds(), 0);
        }
        else
        {

            direction = _direction;
            heldfor /= 2;
            Velocity = new Vector2f(Velocity.X / 1.5f, Velocity.Y);
            if (heldfor < heldforlimit) heldfor++; 
            Velocity += new Vector2f(((speed * (heldfor / 10f)) * direction) * Globals.dt.AsSeconds(), 0);
        }

    }
    public void StopMoving()
    {
        moving = false;
        heldfor = 1;
    }

    public void Update(Time dt)
    {
        if(!moving)
        {
            if(Math.Abs(Velocity.X) - Globals.Friction.X < 0)
            {
                Velocity.X = 0;
            }
            else
            {   // i really should make this direction independent and apply direction at end of the update
                Velocity.X = Velocity.X > 0 ? Velocity.X - Globals.Friction.X : Velocity.X + Globals.Friction.X;
            }
            if (Math.Abs(Velocity.X) <= velocitySnapX) Velocity.X = 0;
            if (Math.Abs(Velocity.Y) <= velocitySnapY) Velocity.Y = 0;
        }
        if (Math.Abs(Velocity.X) > XMaxvel) Velocity.X = XMaxvel * direction;
        if (Math.Abs(Velocity.Y) > YMaxvel) Velocity.Y = YMaxvel * direction;
        Position += Velocity;
    }
}

class Program
{
    Player player = new Player();
    while(game.isrunning) // this is made up as the genuine code is too messy
    {
                    if (Keyboard.IsKeyPressed(Keyboard.Key.Right))
            {
                player.Move(1);
            }
            if (Keyboard.IsKeyPressed(Keyboard.Key.Left))
            {
                player.Move(-1);
            }
            window.Clear(Color.White);
            window.Draw(player);
            player.Update(Globals.dt);
            window.DispatchEvents();
            window.Display();
            window.SetView(mainview);
            Globals.dt = deltaclock.Restart();
    }
}
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

A way to do this is to enforce a maximum cap on your time delta.

Building on Martin Sand's example:

// Get the time delta since last frame.
sf::Time dt = clock.restart();

// Convert to seconds, and clamp to your maximum time step.
float dtAsSeconds = std::min(dt.asSeconds(), 1f/30f);

That way, even if a frame runs really long, the game behaves as though a smaller amount of time passed, slowing down the action relative to wall clock time, rather than jumping ahead to try to catch up.

This can layer on top of a fixed timestep solution as well, leading you to perform fewer fixed ticks this frame to ensure you don't advance the simulation state too far in a single rendered frame.

\$\endgroup\$
1
  • \$\begingroup\$ sorry for answering a literal year later but thanks this probably should work \$\endgroup\$ Commented Oct 24, 2021 at 8:37
0
\$\begingroup\$

I always recommend to start coding with the time step. The time step is the time between the different frames. There are several ways to handle this. The Fix Your Timestep web page summarizes them perfectly. It is kind of a reference.

Please find below same code sample. Code is for Linux but should also compile and work in Windows.

#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
    sf::CircleShape shape(100.f);
    shape.setFillColor(sf::Color::Green);

    window.setFramerateLimit(60);

    // Timing
    sf::Clock clock;

    while (window.isOpen())
    {
        // Update the delta time to measure movement accurately
        sf::Time dt = clock.restart();

        // Convert to seconds to do the maths
        float dtAsSeconds = dt.asSeconds();

        // For debuging, print the time to the terminal
        // It illustrates the differences
        std::cout << "Time step: " << dtAsSeconds << '\n';

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(shape);
        window.display();
    }

    return 0;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .