Verwenden eines Timers zur Positionssteuerung in SFML



  • Hallöle,

    ich habe heute mal das kleine Spiel, welches ich für die Schule als Abschlussprojekt gemacht habe(ein kleines 2D Labyrinth mit SFML 2), auf einem der Schul PCs getestet. Dort ist mir aufgefallen, dass sich der Punkt wesentlich langsamer bewegt als auf meinem PC zuhause. Ich nehme mal stark an, dass die Position pro CPU-Takt verändert. Nun meine Frage, wie kann ich das ganze mit einem Timer realisieren?
    Bitte nur ganz kurz erläutern. Hatte im Internet längere Beispiele gefunden, die aber schlecht bis garnicht kommentiert waren. Sprich ohne Erklärung, nur der Code.
    Verwende Visual Studio 2015 unter dem .Net Framework 4.6.1 mit dem Standardcompiler.

    Vielen Dank im voraus 😃

    Gruß,

    Jonas



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum Spiele-/Grafikprogrammierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Du nimmst eine geeignete Uhr, z.B. aus std::chrono und anstatt die Position um einen fixen Wert vv zu verändern,
    skalierst du diesen Wert stattdessen mit der delta-Zeit, also der Zeit, die zwischen dem letzten und dem aktuellen
    Animations-Frame vergangen ist, also neue_position = alte_position + vv * Δt\Delta t.

    Das Ganze funktioniert in beliebigen Dimensionen (Position und vv sind endweder skalar, ein 2D-Vektor oder 3D-Vektor) und das
    Objekt bewegt sich dann mit v\left|v\right| Längeneinheiten (z.B. Pixel) pro Zeitheinheit (z.B. Sekunde) in Richtung vv.

    Finnegan



  • Hallo Finnegan,
    Danke für deine Information. Aber wie genau kann ich den Timer starten/stoppen? Sprich welche Befehl benötige ich?

    Danke für deine Hilfe 🙂



  • Wie gesagt, std::chrono ist eine gute Wahl. Siehe dazu z.B.:
    http://en.cppreference.com/w/cpp/chrono
    Unten auf der Seite gibt es ein Beispiel, in dem die Zeit bestimmt wird, die für einen Funktionasaufruf benötigt wird. Das was du benötigst ist fast dasselbe.

    Wichtig: Du startest/stoppst für sowas üblicherweise keinen Timer, sondern liest in jedem Frame die aktuelle "Uhrzeit" (möglichst präzise) und bestimmst die vergangene Zeit über die Differenz zum letzten Frame.

    Das läuft grob etwa so ab:

    letzte_zeit = jetzt()
    
    funktion simulationsschritt:
       aktuelle_zeit = jetzt()
       delta_zeit = aktuelle_zeit - letzte_zeit
    
       ... objekte bewegen ...
    
       letzte_zeit = aktuelle_zeit
    

    Finnegan



  • Okay, dankeschön. Und sowas wie in VB, also so einen Timer, gibts in C++ nicht?



  • Kleiner Zusatz (So ungefähr wirds in dem SFML Game-Dev Buch gezeigt (soll jetzt keine Werbung sein)):

    void Application::run()
    {
        sf::Clock clock;
        sf::Time timeSinceLastUpdate;
    
        while (window.isOpen())
        {
            auto delta = clock.restart();
            timeSinceLastUpdate += delta;
            while (timeSinceLastUpdate >= FrameTime)
            {
                timeSinceLastUpdate -= FrameTime;
    
                handleInput();
                update(FrameTime);
            }
    
            render();
        }
    }
    

    Du gibst dann jeder update() Funktion die Zeit und dann machst z.B.

    void Foobar::update(sf::Time dt)
    {
        move(speed * dt.asSeconds());
    }
    

    Glaube das hier ist auch ein Link den man öfters sieht zu dem Thema (hoffe ich hab den richtigen erwischt): http://gafferongames.com/game-physics/fix-your-timestep/



  • Top, dankeschön^^

    Kannst du mir den Link zu dem Buch per PN oder so schicken? Bzw. muss ich einfach nur SFML Buch bei Amazon eingeben oder gibts da mehrere?




Log in to reply