Timer Funktion/ aber nicht Sleep Usleep, da das Programm weiterlaufen soll



  • Hallo,
    ich benötige eine Art Timer. Sowas wie Sleep. (Warte xy Sekunden, und dann gib mir etwas aus.)

    Die Grafiken werden in einer While (1) Schleife dauernd auf das Bild geworfen.
    Programmiere ich nun die Sleep() Funktion ein. dann stockt die Ausgabe-

    Also was machen?
    Wenn meine Schleife an meinem Code vorbei kommt, soll überprüft werden ob das Programm eine bestimmte Zeit lief, dann ausgeben- dann beim erneutem vorbei kommen soll wieder geprüft werden. if aktuelle zeit + xy zeit.
    kenne mich leider in zeit Funktionen kaum aus. Hoffe einer hat ne gute idee.



  • time.h?
    clock()?



  • ja ich denke irgendwas mit clock() wäre das richtige... die schleife while(1) läuft ja immer durch meinen code.. jede milimili sekunde, dann ein wait wäre falsch. dann würde alles stopen. soetwas wie ist ein Zeitvergleich wäre gut. und dann halt ausgeben oder nicht-

    while(1)
    {
    if (clock() > xyspäter)
    {
    // tu es dann wenn if war ist.
    }

    tu das hier immer wieder...
    }

    wie genau muss der code lauten? Blick da nicht durch.



  • Welchen Compiler benutzt du?

    Die WinApi bietet eine Timer Möglichkeit. Hierbei wird alle x ms eine, von dir festgelegte Funktion ausgeführt.

    Gruß
    Ombre



  • Willst du warten? Dann so in der Art:

    int main()
    {
      while (1)
      {
        int begTime = clock();
        // gamecode
        if (clock() - begTime < WAITTIME); // ich nehme mal an dass keine CPU mehr als 1ms für diesen Schritt braucht :D
          Sleep(WAITTIME - (clock() - begTime)); // oder andere Funktion, die wartet ohne CPU-Last zu erzeugen.
        Present(); // Ausgabe
      }
    }
    

    Edit: Bei nicht-Windows Systemen muss man eventuell die vergangene Zeit über CLOCKS_PER_SEC (siehe time.h) ausrechnen. Auf Windows Systemen dürfte clock() aber immer in Millisekunden auflösen..

    Oder willst du dass das Spiel weiter läuft, aber die Ausgabe nicht so oft gemacht wird?

    int main()
    {
      while (1)
      {
        int begTime = clock();
        // gamecode
        if (clock() - begTime > WAITTIME)
          Present(); // Ausgabe
      }
    }
    


  • ich benutze Visual Studio 2010.

    Also das Programm darf nicht anhalten oder Stoppen, Sonst reagiert ja der Rest Code in dem moment nicht. Bedeutet, Eingaben stocken zum Beispiel.
    das alle xsek eine bestimmte Funktion startet hört sich nicht schlecht an.
    ich

    Teste mal deinen zweiten code cooky

    mein Problem ist ja folgendes...

    hier eine Beispielfunktion

    while(1) //Eine Schleife die dauernd läuft.
    {
    //Bestimmte funktion XY
    //hier kann ich kein Sleep oder Wait oder dergleichen verwenden weil sonst mein Ball in dem Moment aufhören würde zu Hüpfen 🙂
    if (Zeit > xyspäter) //also brauche ich etwas wie eine Zeitfunktion
    {
    // tu es dann wenn if war ist.
    }

    tu das hier immer wieder... wegen der Schleife z.B. Ball Hüpft
    }



  • Sooo habe nun das von Cooky getestet

    int main()
    {
    while (1)
    {
    int begTime = clock();
    // gamecode
    int WAITTIME=1 /hab mal Werte zwischen 1und 100 getestet...
    if (clock() - begTime > WAITTIME)
    {
    MeineFunktion_an_einem_bestimmten_Zeitpunkt();
    }
    Die Haupfunktion die immer reagieren sollte();
    }
    }

    Das klappt soweit die Hauptfunktion reagiert flüssig 🙂

    aaaaber die MeineFunktion_an_einem_bestimmten_Zeitpunkt();
    reagiert nur manchmal also nicht regelmässi?! Was für Werte sollte man den Eintragen wenn die zum Beispiel alle 10Sek ausgeführt werden soll`?



  • So wie du das machst, finde ich das nicht sehr gut.
    Du suchst im prinzip eine Möglichkeit, das komplette Game zu timen. Da würde ich einen anderen Ansatz suchen. Berechne das Delta, sprich die Zeit, die ein Frame benötigt. Diesen Wert übergibst du dann an eine Updatefunktion. Dort kannst du dann ausrechnen, ob du reagieren willst oder nicht, wie weit deine Objekte bewegt werden sollen etc etc.

    Meine Loop sieht als Beispiel so aus:

    void NLWindowGL::enterLoop()
    {
        m_ticks     = SystemController().getTimerController().getTicks();
        m_delta     = m_ticks-m_lastTick;
        m_lastTick  = m_ticks;
    
        while ( m_window->IsOpened() )
        {
                    //---------------------------------------------------------
                    // Timing
                    //---------------------------------------------------------
            m_ticks = SystemController().getTimerController().getTicks();
            m_delta = m_ticks-m_lastTick;
            m_lastTick = m_ticks;
    
                    //---------------------------------------------------------
                    // Pump Events
                    //---------------------------------------------------------
                    if (this->pumpEvents() )
                    {
                            //---------------------------------------------------------
                            // Clear Buffers  
                            //---------------------------------------------------------
                            this->beginRender();
    
                            //---------------------------------------------------------
                            // Render-Event  
                            //---------------------------------------------------------
                            m_renderEvent.emit(m_delta, m_ticks);
    
                            //---------------------------------------------------------
                            // Swapping the buffers
                            //---------------------------------------------------------
                            this->endRender();
                    }
        }
    }
    

    Mit Hilfe des Deltas, kannst du nun ganz einfache Berechnungen machen:

    float speed = 1.0f * m_delta;
    

    So lässt sich das sehr einfach berechnen. Oder auch, für deinen 10 Sekunden Timer:

    void meine_funktion(int delta)
    {
       static int timer = 0;
       timer+=delta;
       if (timer >= 10000 )
       {
          mach_was(); 
          timer = 0;
       }
    }
    

    Ich hoffe ich habe das jetzt nicht mißverstanden.

    ps.: Nutze bitte die [ cpp ] Tags. Danke.



  • Zuersteinmal solltest du code-tags benutzen.
    Dann solltest du den code auch verstehen und nicht einfach per copy&paste übernehmen und irgendwelche Werte einsetzen.

    Bei jedem Schleifendurchgang berechnest du die verstrichenen clock-ticks seit dem letzen Schleifendurchgang und akkumulierst sie.
    Sobald der akkumulierte Wert den Grenzwert überschreitet, bei dem deine Funktion ausgeführt werden soll, rufst du diese Funktion eben auf und setzt die Variable mit den akkumulierten Werten wieder auf null.

    clock() gibt dir übrigens keine Zeitangabe, sondern wie schon erwähnt clock-ticks.
    Für 10 Sekunden solltest du also CLOCKS_PER_SECOND * 10 clock-ticks warten.



  • Der Vorschlag von Scorcher24 ähnelt einer Spielschleife. Ist also im Prinzip ein guter Ansatz.

    Wenn du damit nicht parat kommst, kannst du erstmal mit den WINAPI Funktionen arbeiten.

    Hierfür legst du eine Variable fest =

    const int Timer = 1;
    

    Dann startest du z.B. in der Main den Timer:

    SetTimer(hWnd, Timer, 1000, NULL);
    

    Der erste Wert ist der Handle zu deinem Fenster, der zweite Wert ist der Timer, der dritte Wert der Intervall in Millisekunden und der vierte uninteressant 🙂

    In der CallBack Funktion reagierst du auf die Nachricht WM_TIMER :

    case WM_TIMER
        switch(wParam)
        {
        case Timer:
            //hier machen was gemacht werden soll
            return 0;
        }
        return 0;
    

    Vor Beendung des Programms musst du den Timer wieder "Killen":

    KillTimer(hWnd, Timer);
    

    Gruß
    Ombre

    ps: Trotzdem ist eine Spielschleife immer die bessere Wahl, wobei ich finde das man auch die WINAPI Funktionen kennen sollte ... Bei einer Spielschleife wird die Framerate gemessen und genutzt um etwas flüssig und ruckel / flackerfrei darzustellen.



  • @Ombre

    ich glaube die SetTimer nutzt die Windows.h ?
    Das SDK ist fürs Iphone (ich nutze das Visual Studio nur als Programmierumgebung) es gehen nur c++ Standard Bibliotheken, leider nicht die o.g. deshalb wird SetTimer nicht so einfach funktionieren können.



  • aloa 🙂

    soooooooo mein problem ist perfekt gelöst 🙂
    habe mal im Forum nach dem Problem gesucht und jemand hat eine Super Lösung angeboten:

    http://www.c-plusplus.net/forum/262398?highlight=clockspersec
    Dies Funktioniert genau wie ich das brauche.
    nun muss ich nur noch den Code verstehen 🙂



  • Dir ist aber schon klar, dass sich das nicht von meiner zweiten Lösung unterscheidet? 😃
    Zudem belastest du die CPU so dauerhaft zu 100%, ich weiß ja nicht ob das bei iPhones so üblich ist, aber wenn da keine ARM CPUs drin stecken ist das doof.

    Am besten wäre es, das Spielgeschehen der vergangenen Zeit anzupassen.



  • hi cooky-
    deine zweit Lösung war Super 🙂
    nur Leider komisch ungenau. wurde die Funktion ausgelöst, dann wieder nicht, dann 3 mal hintereinander ganz schnell...
    irgendwas fehlte da noch. wie kriegen wir den Code den so angepasst das es flüssig läuft`?

    Sorry das ich noch nicht so das verständnis für den Code habe.
    mein weg zu lernen ist irgendwie anders rum, erst mal was bauen, dannach verstehen warum und wieso das geht.

    das ist die SDK
    http://www.airplaysdk.com/features_desktoparmdebugging.php
    ich denke ARM cpu sollte drin sein.



  • Hm.. die Frage ist, wie lange present() dann im Endeffekt braucht. Vielleicht gehts so besser?:

    int MyTimer(int time, int expected)
    {
      static int lastTime = 0;
      if (lastTime <= 0)
        lastTime = time;
      if (time - lastTime >= expected)
      {
        lastTime = time;
        return 1;
      }
      return 0;
    }
    
    int main()
    {
      int i = 0;
      while (1)
      {
        // game code
        if (MyTimer(clock(), 1000))
          printf("%i\n", ++i);
      }
    }
    

    Ersetze printf() durch present() und 1000 durch die Zeit die du halt haben willst.

    Nur wie gesagt, gibt es fürs iPhone keine Grafiklib oder so? Dann sollte man die benutzen, VSync anschalten, und dann jede Bewegung zeitabhängig berechnen. Das ist zwar etwas mehr Aufwand, aber es lohnt definitiv. Denn so zB. läuft dein Code auf langsameren iPhones auch langsamer, also deine Autos (oder was auch immer) fahren dann auch langsamer.

    Edit:
    Zudem ist es nicht gerade ratsam direkt für ein iPhone zu programmieren, wenn man die C Grundzüge noch nicht mal drauf hat..



  • ich glaub nicht dass eure Beispiele Frameschleifen gut sind...

    Wenn ein Objekt sich bewegt und plötzlich braucht das System 2 sek bis zum nächsten Renderbilder. In diesem Moment will das Objekt 3 Schüsse abfeuern, die Position, von wo es aus geschossen wird, wurde nicht berechnet. Ein sprunghaftes Objekt, 3 Schüsse von der selben Position wäre ein störendes Verhalten.



  • xBlackKnightx schrieb:

    ich glaub nicht dass eure Beispiele Frameschleifen gut sind...

    Wenn ein Objekt sich bewegt und plötzlich braucht das System 2 sek bis zum nächsten Renderbilder. In diesem Moment will das Objekt 3 Schüsse abfeuern, die Position, von wo es aus geschossen wird, wurde nicht berechnet. Ein sprunghaftes Objekt, 3 Schüsse von der selben Position wäre ein störendes Verhalten.

    Joa, alles lesen schadet manchmal dann doch nicht 😃 Auf das Problem wurde bereits hingewiesen, aber der TE hatte explizit nach einer Möglichkeit gefragt, die Ausgabe nicht jedes mal zu machen. Zudem ist das Beispiel von Scorcher24 sogar noch darauf eingegangen 🙄



  • Guten Morgen,

    ich hab noch nen paar kleine Frage zu dem Code von Scorcher.

    1.Gehe ich recht in der Annahme, dass ab den PUMP Events der eigene Code stehen kann, der ausgeführt werden soll ?

    2.Bei diesem Game loop habe ich doch auch immer 100% CPU Auslastung, oder?
    Ich meine ich befinde mich doch immer in der while Schleife ? (m_window->isOpened() nehme ich mal an gibt true zurück, wenn das Fenster angezeigt wird ?)

    3. Wenn ich eh immer in der while Schleife bin, wieso setz ich dann die Variablen m_ticks, m_delta, m_lasttick neu ? Ich arbeite mit denen ja gar nicht ?

    4. Ich hab jetzt mal nach "c++ game loop" gegoogelt und bisher keine loops gefunden, die annähernd an den loop von Scorcher rankommen. Ich finde nur loops mithifle von SDL oder loops mithifle der winapi. Könntet ihr mir bitte den code von Scorcher erklären oder einen link geben bei dem das etwas erklärt ist ?

    Schonmal Vielen Dank!

    Gruß
    Panamajay

    void NLWindowGL::enterLoop()
    {
        m_ticks     = SystemController().getTimerController().getTicks();
        m_delta     = m_ticks-m_lastTick;
        m_lastTick  = m_ticks;
    
        while ( m_window->IsOpened() )
        {
                    //---------------------------------------------------------
                    // Timing
                    //---------------------------------------------------------
            m_ticks = SystemController().getTimerController().getTicks();
            m_delta = m_ticks-m_lastTick;
            m_lastTick = m_ticks;
    
                    //---------------------------------------------------------
                    // Pump Events
                    //---------------------------------------------------------
                    if (this->pumpEvents() )
                    {
                            //---------------------------------------------------------
                            // Clear Buffers  
                            //---------------------------------------------------------
                            this->beginRender();
    
                            //---------------------------------------------------------
                            // Render-Event  
                            //---------------------------------------------------------
                            m_renderEvent.emit(m_delta, m_ticks);
    
                            //---------------------------------------------------------
                            // Swapping the buffers
                            //---------------------------------------------------------
                            this->endRender();
                    }
        }
    }
    


  • Panamajay schrieb:

    1.Gehe ich recht in der Annahme, dass ab den PUMP Events der eigene Code stehen kann, der ausgeführt werden soll ?

    Jain. Aber es könnte Sinn machen. Du schreibst alles nach PumpEvents was abhängig von PumpEvents ist 😉
    (Also "nach vorne laufen" zB.)

    Panamajay schrieb:

    2.Bei diesem Game loop habe ich doch auch immer 100% CPU Auslastung, oder?
    Ich meine ich befinde mich doch immer in der while Schleife ? (m_window->isOpened() nehme ich mal an gibt true zurück, wenn das Fenster angezeigt wird ?)

    Das Problem ist, dass dieser Code davon ausgeht, dass ein Framework zur Verfügung steht das dann bei present() auf VSync wartet. Dann wird nicht 100% CPU Last erzeugt.

    Panamajay schrieb:

    3. Wenn ich eh immer in der while Schleife bin, wieso setz ich dann die Variablen m_ticks, m_delta, m_lasttick neu ? Ich arbeite mit denen ja gar nicht ?

    Doch und genau das sollte der Code eigentlich zeigen. Du guckst wie viel Zeit vergangen ist und berechnest dann je nach dem die neue Position aller Objekte.

    Diesen Code so für ein iPhone zu übernehmen macht aber wenig Sinn. Wie gesagt, gibt's denn da kein Spiele-/Grafik-Framework oder sowas?

    Edit: Ach, du bist ja gar nicht der TE 😃
    Für welches System willst du programmieren und mit welchem Framework / Grafik API?



  • Hallo,

    erstmal danke für die antworten. Ich hab mir nur mehrere Threads angesehen und hab mir mal die Quellcodes angesehen. Da ich noch ein Anfänger bin was C++ angeht, habe ich versucht die Quellcodes dann zu verstehen bzw. mal gesehen wie andere Programmierer ihr Programm aufbauen.

    Momentan lese ich mich noch etwas in der STL und der WinApi ein 🙂

    Gruß
    Panamajay


Anmelden zum Antworten