Jo, danke David,
es scheint also seine Berechtigung zu besitzen, also habe ich meine Finger davon gelassen
Nun aber zur Frameratenbremse. Dazu habe ich die tbDoMessageLoop() umgeschrieben. Jetzt verhält sie sich wie vorher auch, nur hat noch besagte Erweiterung bekommen. Man kann die alte also durch diese ersetzen und weiterhin wie gehabt verwenden, ohne Einschränkungen zu erfahren (sollte zumindest so sein). Wem das aber trotzdem nicht ganz geheuer ist, kann sie ja nur einfügen und in z.B. tbDoMessageLoopBrake() umtaufen, so dass man zwischen beide im Hauptprogramm wählen kann.
Zur umgeschriebenen tbDoMessageLoop() habe ich noch eine kleine Funktion namens tbSetFramebrake() eingeführt, mit der man auch während des Spiels noch die Bremse umstellen kann.
Kommen wir zu den Änderungen.
in der TriBase.h:
unter den globalen externen Variablen folgende einfügen:
|
Quellcode
|
1
|
extern double tb_g_dFramebrake; // Framebremse, die maximale Framezahl umgerechnet mit Kehrwert
|
die alte tbDoMessageLoop() durch folgendes ersetzen (bzw. diehier umbenennen):
|
Quellcode
|
1
2
3
4
|
TRIBASE_API tbResult tbDoMessageLoop(tbResult (* pMoveProc)(float),
tbResult (* pRenderProc)(float),
double dMaxFPS = 1000); // Nachrichtenschleife
TRIBASE_API tbResult tbSetFramebrake(double dFramebrake); // Setzen der neuen Frameratenbegrenzung
|
in der TriBase.cpp:
folgende globale Variable einfügen
|
Quellcode
|
1
|
double tb_g_dFramebrake = 1000.0; // Framebremse, die maximale Framezahl
|
irgendwo die neue Funktion einfügen (ich hab sie direkt über der Nachrichtenschleife sollte aber egal sein)
|
Quellcode
|
1
2
3
4
5
6
7
8
9
|
// ******************************************************************
// Framebremse setzen
TRIBASE_API tbResult tbSetFramebrake(double dFramebrake)
{
if(dFramebrake == 0.0) dFramebrake = 1000.0;
tb_g_dFramebrake = 1.0 / dFramebrake;
return TB_OK;
}
|
und die Nachrichtenschleife selbst ersetzen (bzw. umbenannt einfügen)
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
// ******************************************************************
// Nachrichtenschleife
TRIBASE_API tbResult tbDoMessageLoop(tbResult (* pMoveProc)(float),
tbResult (* pRenderProc)(float),
double dMaxFPS)
{
MSG Message; // Nachricht
LONGLONG llStartTime; // Startzeitpunkt
LONGLONG llEndTime; // Endzeitpunkt
double dTime; // Zeitspanne in Sekunden
BOOL bQuit = FALSE;
// Frameratenbremse setzen
tbSetFramebrake(dMaxFPS);
TB_INFO("Nachrichtenschleife wird betreten...");
ZeroMemory(&Message, sizeof(MSG));
// Startzeitpunkt vorab messen für die erste Schleife
QueryPerformanceCounter((LARGE_INTEGER*)(&llStartTime));
// Nachrichtenschleife
dTime = 0.0001;
while(!bQuit)
{
// Nachrichten verarbeiten
while(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
if(Message.message == WM_QUIT)
{
// Schleife verlassen!
bQuit = TRUE;
}
}
if(tb_g_bAppActive)
{
// Die Sekunden seit dem letzten Frame speichern
tb_g_dNumSecsPassed = dTime;
// Bewegungen durchführen, falls gewünscht
if(pMoveProc != NULL) if(pMoveProc((float)(dTime)) == TB_STOP) break;
// Frameratenzähler vor dem rendern midestens einmal durchlaufen und ggf. abbremsen
do{
// Endzeitpunkt messen und Anzahl der vergangenen Sekunden berechnen
QueryPerformanceCounter((LARGE_INTEGER*)(&llEndTime));
if(llEndTime == llStartTime) dTime = 0.0001;
else dTime = (float)(llEndTime - llStartTime) / tb_g_dFrequency;
}while(dTime < tb_g_dFramebrake);
// Zeitzähler erhöhen
tb_g_fTime += (float)(dTime);
// Neuen Startzeitpunkt nach der Framebremse berechnen
QueryPerformanceCounter((LARGE_INTEGER*)(&llStartTime));
// Spielzustand zeichnen, falls gewünscht
if(pRenderProc != NULL) if(pRenderProc((float)(dTime)) == TB_STOP) break;
if(tbDirectSound::IsInitialized())
{
if(tbDirectSound::GetListener() != NULL)
{
// Aufgeschobene 3D-Sound-Änderungen wirksam machen
tbDirectSound::GetListener()->CommitDeferredSettings();
}
}
}
}
TB_INFO("Nachrichtenschleife beendet!");
return TB_OK;
}
|
Das müsste es gewesen sein. Beten nicht vergessen!
Jetzt kann man beim Aufruf der tbDoMessageLoop() als dritten Parameter die maximale Framerate angeben. Tut man das nicht, läuft alles wie gehabt (hoffe ich zumindest :wirbel: ).
Das Kernstück ist ja die die do-while-Schleife
|
Quellcode
|
1
2
3
4
5
6
7
|
// Frameratenzähler vor dem rendern midestens einmal durchlaufen und ggf. abbremsen
do{
// Endzeitpunkt messen und Anzahl der vergangenen Sekunden berechnen
QueryPerformanceCounter((LARGE_INTEGER*)(&llEndTime));
if(llEndTime == llStartTime) dTime = 0.0001;
else dTime = (float)(llEndTime - llStartTime) / tb_g_dFrequency;
}while(dTime < tb_g_dFramebrake);
|
Ich habe sie zwischen Berechnung und Rendern gepackt, weil es für mich logischer klang, denn wenn man eine Frameratenbremse einbaut, dann hat man (zumindest bei 2D) eine ziemlich konstante Rendermethode, so dass der variable Zeitfaktor in der Berechnung von Move liegt. Wenn die Berechnung also mal schneller fertig ist, dann soll sie halt vor dem rendern warten und berstimmt nicht danach.
Ok, das wärs dann...
...fürs erste