Deutsch
Quelltexte/ Codesnippets

Konstante Bildrate / Framerate für Spiele

 

Sven
Bader
Nachdem ich in meinem letzten Quelltext die Genauigkeit von "Sleep" gefixt habe, hier nun ein etwas umfangreicheres Beispiel für eine konstante Framerate in Spielen. Bisher hatte ich mit pro Frame aufsummierten Rundungsfehlern gelebt und Bildberechnung und Logik (Ticks) immer gemeinsam abgewickelt, hier funktioniert beides besser!

Features:
-Verwendung eines präzisen Perfomance Counters
-Physik läuft weiter, auch wenn die Bildberechnung hinterherhinkt
-Framerate abweichend von Ticks wählbar
-kein Aufsummieren von Zeitabweichungen
-Sleep für verbleibende Frame-Zeit (0% CPU), außer letzter Rest mit genauem Performance Counter

Einschränkungen:
-keine automatische Anpassung der Framerate, nur Bilddrops
-Framerate nur als vielfaches von Ticks wählbar (jeder, jeder Zweite, jeder Dritte,...)
-Gar kein Bild, wenn Zeit nicht einmal für Physik ausreicht (Drop jedes Frames)

Alles wäre machbar, ich wollte es nicht zu komplex machen. Zudem müsste bei OpenGL abgefragt werden, ob VSync verwendet wird, da die FPS hier bereits durch OpenGL auf die Bildrate des Monitors gekappt werden.


Declare qpc#, freq_factor!, qpc_freq#, caps#
Declare  timeNextFrame!,timeNextFrameSecure!,timeend!,ticks&
Declare framedrop&,mod&, frame&,countFramedrops&
Dim qpc#,8'Performance Counter aktuelle Zeit
Dim qpc_freq#,8'Performance Counter Frequenz
Dim caps#,8'Timer Intervalle min/max auslesen
Def timeGetDevCaps(2) !"winmm","timeGetDevCaps"
Def timeBeginPeriod(1) !"winmm","timeBeginPeriod"
Def timeEndPeriod(1) !"winmm","timeEndPeriod"
Def QueryPerformanceFrequency(1) !"Kernel32","QueryPerformanceFrequency"
Def QueryPerformanceCounter(1) !"Kernel32","QueryPerformanceCounter"
WindowStyle 16'+ 64
Window (%maxx * 0.5 - 250), (%maxy * 0.5 - 262) - 500,524
QueryPerformanceFrequency(qpc_freq#)'Performance Counter Frequenz
freq_factor! = (1 / (long(qpc_freq#,0) / 1000.0))'macht die spätere Umrechnung lesbarer
'Benutzereinstellungen
ticks& = 120'Ticks sind Physik-Frames pro Sekunde
mod& = 1'Jeder wievielte Tick wird ein Bild gezeichnet? 1 wenn fps = ticks
timeGetDevCaps(caps#,8)'Auflösung des Timers anfragen (caps# =  min ms, max ms)
timeBeginPeriod(long(caps#,0))'minimale Auflösung des Timers setzen, da auf manchen Systemen Sleep sonst nur 15ms genau ist!!
'Physikzeug, Position und Geschwindigkeit
declare x&,y&,speedx&,speedy&
speedx& = 1
speedy& = 1
x& = 77
y& = 299
declare mousekey1&,mousekey2&
timeNextFrameSecure! = 1
mcls 500,500

whilenot iskey(27)'ESC

    inc frame&
    'Manuelle Änderung der FPS und Ticks

    if (iskey(1)) AND not(mousekey1&)

        inc mod&
        mousekey1& = 1

    endif

    casenot (iskey(1)) : mousekey1& = 0
    case mod& > 8 : mod& = 1

    if (iskey(2)) AND not(mousekey2&)

        ticks& = ticks& + 30.0
        mousekey2& = 1

    endif

    casenot (iskey(2)) : mousekey2& = 0
    case ticks& > 240 : ticks& = 30.0
    '1. PHYSIK
    case (x& <= 16)  OR (x& >= 484)  : speedx& = speedx& * (-1)
    case (y& <= 16)  OR (y& >= 484)  : speedy& = speedy& * (-1)
    x& = x&+speedx&
    y& = y&+speedy&
    '2. GRAFIK

    if (frame& = 1) OR (not(framedrop&)  AND (frame& MOD mod& = 0))

        startpaint -1
        cls RGB(192,192,192)
        UsePen 0,0,RGB(0,128,192)
        TextColor RGB(40,40,40),-1
        UseBrush 1, RGB(0,128,192)
        Ellipse (x&-16),(y&-16) - (x&+16),(y&+16)
        DrawText 16, 16, str$(countFramedrops&) + " drops (Bilder übersprungen)"
        DrawText 16, 32, str$(int(ticks&)) + " ticks (Physik/Logik pro Sekunde)"
        decimals 1
        DrawText 16, 48, str$((ticks& / mod&)) + " fps (Bilder pro Sekunde, mod& = "+str$(mod&)+")"
        DrawText 16, 80, "Linke Maustaste ändert FPS"
        DrawText 16, 96, "Rechte Maustaste ändert Ticks"
        DrawText 16, 112, "ESC zum Beenden"
        endpaint
        MCopyBmp 0,0 - 500,500 > 0,0;0

    endif

    '3. TIMING
    'ungenaues Sleep bis kurz vor gewünschtem Frame-Ende

    if int(timeend!) < int(timeNextFrameSecure!)

        sleep int(timeNextFrameSecure!) - int(timeend!)
        framedrop& = 0

    else

        framedrop& = 1
        inc countFramedrops&

    endif

    'Restliche Zeit mit genauem Performance-Counter abwarten
    'mindestens ein Duchlauf, um die aktuelle Zeit zu holen

    while timeend! < timeNextFrame!

        QueryPerformanceCounter(qpc#)'Endzeit des Counters
        timeend! = long(qpc#,0)  * freq_factor!
        'Sollte ausser beim ersten Frame nicht passieren, wird andernfalls aber auch hiermit gerettet

        if abs(timeend! - timeNextFrame!) > 2000

            timeNextFrame! = timeend! + (1000.0 / ticks&)'Versuch es zu retten

        endif

    endwhile

    timeNextFrame!       = timeNextFrame! + (1000.0 / ticks&)' Endzeit für nächsten Frame
    timeNextFrameSecure! = timeNextFrame! - 2.0' und nochmal 2ms früher

endwhile

timeEndPeriod(long(caps#,0))'zuvor gesetzte minimale Timer-Auslösung zurücksetzen
Dispose caps#, qpc_freq#, caps#, qpc#, qpc_freq#

9 kB
Hochgeladen:02.02.2023
Ladeanzahl56
Herunterladen
 
02.02.2023  
 




Georg
Teles
Nabend,

sehr gut, nu kann ich meinen 144 Hz Monitor auch mit XProfan testen

Grüße
 
Alle Sprachen
TC-Programming [...] 
XProfan 8.0 - 10.0 - X2 - X3 - X4

05.02.2023  
 



Zum Quelltext


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

1.557 Betrachtungen

Unbenanntvor 0 min.
Sven Bader10.07.2023
Wilfried Friebe28.05.2023
funkheld14.05.2023
Alibre01.05.2023
Mehr...

Themeninformationen

Dieses Thema hat 2 Teilnehmer:

Georg Teles (1x)
Sven Bader (1x)


Admins  |  AGB  |  Anwendungen  |  Autoren  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Händlerportal  |  Impressum  |  Mart  |  Schnittstellen  |  SDK  |  Services  |  Spiele  |  Suche  |  Support

Ein Projekt aller XProfaner, die es gibt!


Mein XProfan
Private Nachrichten
Eigenes Ablageforum
Themen-Merkliste
Eigene Beiträge
Eigene Themen
Zwischenablage
Abmelden
 Deutsch English Français Español Italia
Übersetzungen

Datenschutz


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie