160 likes | 287 Views
Loops Jason Gregory : Game Engine Architecture. Tobias Kemper Softwaretechnologie II (Teil 2) HKI Uni Köln SS 2013. Zeit. Unterschiedliche Arten von Zeit Real time Game time Local timeline. Loops. Rendering Loop Neuberechnung des Bildschirminhalts für jedes einzelne Frame
E N D
LoopsJason Gregory : Game Engine Architecture Tobias Kemper Softwaretechnologie II (Teil 2)HKI Uni Köln SS 2013
Zeit • Unterschiedliche Arten von Zeit • Real time • Game time • Local timeline
Loops • Rendering Loop • Neuberechnung des Bildschirminhalts für jedes einzelne Frame • Für die Erzeugung der Illusion von Bewegtbildern While (!quit){updateCamera();updateSceneElements();renderScene();swapBuffers();}
Loops • Game Loop • Unterhält die interagierenden Subsysteme • Periodisches Updaten der Systeme in unterschiedlichen Raten • Masterschleife
void main() // Pong { initGame(); while (true) // game loop{ readHumanInterfaceDevices(); if (quitButtonPressed()){ break; // exit the game loop } movePaddles(); moveBall(); collideAndBounceBall(); if (ballImpactedSide(LEFT_PLAYER)){ incremenentScore(RIGHT_PLAYER); resetBall(); } else if (ballImpactedSide(RIGHT_PLAYER)){ incrementScore(LEFT_PLAYER); resetBall(); } renderPlayfield(); } }
Game Loop Architecture • Windows Message Pumps • Nachrichtenschleife, die auf Nachrichten von Windows "lauscht" und nur wenn alle abgearbeitet sind, wieder die Engine arbeiten lässt • Callback-Driven Frameworks • in framework basierten engines wurde die Haupt Game loop schon geschrieben und wird vom Programmierer mit Callback-Functionsgefüllt • Event-BasedUpdating • Event System im Spiel behält Überblick über „interessante“ Statusänderungen und updated die Subsysteme
Abstract Timelines • abstrakten Zeitachsen, die relativ zu anderen im System liegen können • RealTime wird dabei über den CPU internen Timer in CPU-Cycles gemessen • GameTime ist unabhängig von der RealTime und kann für verschiedene Effekte genutzt werden • Lokale Zeitachsen für video/animation/audio
Zeit messen und mit Zeit arbeiten • Menge der Zeit die zwischen Frames vergeht ist bekannt als "Delta Time" Δt • 30 FPS -> Δt = 1/30 einer Sekunde • Berechnung von Geschwindigkeit (Bsp Raumschiff) • Geschwindigkeit v * Δt = Änderung der Position Δx • Wichtig: Zeit CPU-Unabhängig machen
Zeiteinheiten und Variablen • 64-Bit Integer Zeitmesser • Extreme Präzision • 32-Bit Integer • Kurze Zeitabstände mit hoher Präzision • 32-Bit Fließkomma • Nur für kurze Δt von maximal wenigen Minuten (eher nur single-frame oder weniger) • 1/300 Sekunde Zeiteinheit
Multiprocessor Game Loops • Multicore Prozessoren -> Verlagerung hin zu paralleler Datenverarbeitung • Multithreaded Programmdesign • Nutzung der Hardware maximieren • Ruhezeit minimieren
Multicore Architektur nutzen • „SIMD“ • „ForkandJoin“ • „One Thread per Subsystem“ • „Jobs“
Netzwerk Multiplayer Game Loops • Client-Server Modell • Peer-to-Peer
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, intnCmdShow) { MSG msg; int time, oldtime, newtime; char *cddir; ParseCommandLine (lpCmdLine); Qcommon_Init (argc, argv); oldtime = Sys_Milliseconds (); /* main window message loop */ while (1) { // Windows message pump. while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) { if (!GetMessage (&msg, NULL, 0, 0)) Com_Quit (); sys_msg_time = msg.time; TranslateMessage (&msg); DispatchMessage (&msg); } // Measure real delta time in milliseconds. do { newtime = Sys_Milliseconds (); time = newtime - oldtime; } while (time < 1); // Run a frame of the game. Qcommon_Frame (time); oldtime = newtime; } // never gets here return TRUE; }
void Qcommon_Frame (intmsec) { char *s; inttime_before, time_between, time_after; // [some details omitted...] // Handle fixed-time mode and time scaling. if (fixedtime->value) msec = fixedtime->value; else if (timescale->value) { msec*= timescale->value; if (msec < 1) msec = 1; } // Service the in-game console. do { s = Sys_ConsoleInput (); if (s) Cbuf_AddText (va("%s\n",s)); } while (s); Cbuf_Execute(); // Run a server frame. SV_Frame(msec); // Run a client frame. CL_Frame(msec); // [somedetailsomitted...] } // never gets here return TRUE; }