Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Thread GENAU alle 10ms ausführen (https://www.delphipraxis.net/186282-thread-genau-alle-10ms-ausfuehren.html)

idefix2 20. Aug 2015 10:25

AW: Thread GENAU alle 10ms ausführen
 
Ich vermute, es geht dir darum, dass die Abläufe immer gleich schnell wirken. Dabei ist es relativ egal, ob der einzelne Durchlauf 8, 10 oder 11 ms nach dem vorigen Durchlauf erfolgt, aber Fehler dürfen nicht akkumulieren.

Zu Beginn:
Code:
TickCountAtStart:=gettickcount;
StepCount:=0;
und
nach jedem Durchlauf:
Code:
inc(StepCount,TicksPerStep);
sleep(TickCountAtStart+StepCount-gettickcount);

Mavarik 20. Aug 2015 13:06

AW: Thread GENAU alle 10ms ausführen
 
So mach ich es auch...

Delphi-Quellcode:
procedure TMainTimeing.Execute;
var
 Timer : TStopWatch;
 MS   : Int64;
 FPS  : Single;
begin
  Timer := TStopWatch.Create;
  Timer.Reset;

  while not(GameEnd) do
    begin
      try
        Timer.Start;

        GameScreen.Bereinigen;
        GameScreen.BeginUpdate;
        try
          try
            FPS := PacMan.NextFrame;
          except
            MS := 1;
          end;
        finally
          GameScreen.EndUpdate;
        end;

        TThread.Synchronize(NIL,Procedure()
        begin
          PacForm.BeginUpdate;
          try
            PacForm.Image1.Bitmap.Assign(GameScreen.Screen[GameScreen.AktScreen]);
          finally
            PacForm.EndUpdate;
          end;
        end);

        Timer.Stop;
        MS := Timer.ElapsedMilliseconds;
        Timer.Reset;

        if MS < FrameRate then
          Sleep(FrameRate-MS);
      except
        GameEnd := true;
      end;
    end;
end;

Medium 20. Aug 2015 20:59

AW: Thread GENAU alle 10ms ausführen
 
Die Sache mit dem Sleep fällt jedoch komplett in sich zusammen, wenn der Code im Thread länger braucht als die maximale Sleep-Zeit nachher sein soll. Den negativen Wert kann man ja noch auf 0 clampen, aber wenn die gesamte Mechanik darauf ausgelegt ist, dass der Thread immer schneller als sein Intervall ist, bricht praktisch alles zusammen.

Ich gehe noch davon aus, dass es hier um die Frame-Update Methode geht, was der TE glaube ich noch nicht bestätigt hat:
Der einzig richtige Weg ist es, die Framerate überhaupt nicht zu kontrollieren, das kann eigentlich nur schief gehen. Entweder man lässt es so schnell laufen wie es geht, oder, wenn man DirectX oder OpenGL einsetzt, man limitiert auf V-Sync.
Der Kniff ist: Nicht die Framerate orientiert sich an der Spiellogik, sondern die Logik ist zeitlich skalierbar und an die Framerate anpassbar! Im Grunde muss man "nur" vorsehen, dass alle "Fortschritte", also alle zeitlichen Abläufe, ein gemeinsames Basisintervall annehmen, und dann einen Faktor entgegennehmen an den angepasst wird. Der Faktor ergibt sich dann aus der Verarbeitungsgeschwindigkeit von direkt davor.
Damit bleiben alle Abläufe konstant, ganz egal wie schnell der PC ist. Man hat zwar potenziell ein Frame "Lag", da man immer auf den letzten anpasst (an den aktuellen geht ja nicht), aber im Mittel kommt das sehr gut hin, krasse Sprünge sind eher selten, und in der Gesamtheit passt es - ganz ohne kumulierte Fehler. Alles andere ist Gehampel, dass einem früher oder später um die Ohren fliegt.

hathor 20. Aug 2015 21:35

AW: Thread GENAU alle 10ms ausführen
 
Zitat: "Ich möchte aber dass der Thread immer 10 ms braucht."

Da kann man alles, was mit SLEEP() oder SLEEPEX() zu tun hat, vergessen.
Es wird nur eine Mindestzeit "geschlafen", aber nach oben gibt es keine Funktionsgarantie, d.h. es kann auch mal 15,6 ms dauern, statt die gewünschten 1 bis 10.

SleepEx function

Mavarik 20. Aug 2015 21:57

AW: Thread GENAU alle 10ms ausführen
 
Zitat:

Zitat von hathor (Beitrag 1312938)
Zitat: "Ich möchte aber dass der Thread immer 10 ms braucht."

Eben... Er hat nicht geschrieben: alle 10ms auch wenn meine Berechnung länger dauert...

Also gehe ich mal davon aus, das er schneller brechnet...

BTW..: ohne den Sleep schafft meine Pucman routine 480-550 Frames.

Dejan Vu 21. Aug 2015 08:07

AW: Thread GENAU alle 10ms ausführen
 
@idefix2, @Mavarik: Siehe #5 :-D

p80286 21. Aug 2015 11:19

AW: Thread GENAU alle 10ms ausführen
 
Um noch einmal klar zu stellen was geschrieben wurde:
Zitat:

Zitat von Cubysoft (Beitrag 1312788)
Dabei soll eine Berechnung genau alle 10ms ausgeführt werden und das in einem anderen Thread.
...
Problem ist nun halt, dass die Berechnung hierbei stark von dem benutzten PC abhängt. Wenn der Codeblock bei schnelleren PCs 5ms braucht, braucht er bei langsamen vllt 10. Ich möchte aber dass der Thread immer 10 ms braucht. Und nicht wie bei dem Beispiel 15ms oder 20ms..

Gruß
K-H

Mavarik 21. Aug 2015 11:50

AW: Thread GENAU alle 10ms ausführen
 
Zitat:

Zitat von Dejan Vu (Beitrag 1312958)
@idefix2, @Mavarik: Siehe #5 :-D

daher

Zitat:

Zitat von Mavarik (Beitrag 1312857)
So mach ich es auch...


Zitat:

Zitat von p80286 (Beitrag 1312985)
Um noch einmal klar zu stellen was geschrieben wurde:

Logisch - Weil er in seinem Beispiel nicht die länge der Ausführung berücksichtigt hat und daher immer 10ms länger wartet...

idefix2 21. Aug 2015 15:11

AW: Thread GENAU alle 10ms ausführen
 
Eine andere Variante wäre es, via Timer alle 10 ms die Aktion zu starten - wenn du dich darauf verlassen kannst, dass du in 10ms immer fertig wirst.
Wenn die Timer Routine noch läuft, wird allerdings der nächste Durchlauf übersprungen, während bei der Variante mit sleep der nächste Durchlauf sofort angehängt wird, und wenn ein Durchlauf im Schnitt nicht länger als 10ms dauert, die Verspätung aufgeholt werden kann.

Medium 22. Aug 2015 03:15

AW: Thread GENAU alle 10ms ausführen
 
Hier in der DP steht bestimmt schon mehrere hundert Male warum ein Timer für präzise Timings, vor allem unter 40ms/25ms komplett ungeeignet ist. Du bist doch schon lange dabei idefix, noch nie grüber gestolpert? (Davon ab wären auch "perfekte" Timer ungeeignet, zumindest wenn es wirklich um die Framerate in einem Spiel geht. Leider hat der TE das Thema hier offenbar schon verlassen, Nachfragen werden ja nicht beantwortet. Von daher...)


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:02 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz