2010-11-28 5 views
5

Ich schreibe gerade ein Spiel von immenser Kultiviertheit und List, das dich mit Ehrfurcht erfüllen und gewinnen wird - oh, OK, es ist das 15-Puzzle, und ich lerne mich nur mit SDL vertraut.Wie synchronisiert man Seiten-Flips mit vertikalem Rücklauf in einer windowed SDL-Anwendung?

Ich bin im Fenstermodus und SDL_Flip als General-Fall-Seite-Update ausgeführt, da es automatisch auf eine SDL_UpdateRect des vollständigen Fensters im Fenstermodus zugeordnet. Nicht der optimale Ansatz, aber vorausgesetzt, dass dies nur das 15 Puzzle ist ...

Wie auch immer, die Fliesen bewegt sich mit lächerlicher Geschwindigkeit. IOW, SDL_Flip im Fenstermodus enthält keine Synchronisierung mit vertikalen Rückverfolgungen. Ich arbeite in Windows XP ATM, aber ich nehme an, das ist das richtige Verhalten für SDL und wird auch auf anderen Plattformen auftreten.

Die Umstellung auf SDL_UpdateRect ändert offensichtlich nichts. Vermutlich muss ich die Verzögerungslogik in meinem eigenen Code implementieren. Aber ein einfacher Clock-basierter Timer könnte zu Aktualisierungen führen, wenn das Fenster halb gezeichnet wird, was zu sichtbaren Verzerrungen führt (ich vergesse den technischen Namen).

EDIT Dieses Problem ist bekannt als "Tearing".

Also, wie synchronisiere ich in einem Fenstermodus-Spiel in SDL meine Seiten-Flips mit dem vertikalen Rücklauf?

EDIT Ich habe mehrere Ansprüche gesehen, während der Suche nach einer Lösung, dass es unmöglich ist, zu dem vertikalen Rücklauf in einem Fensteranwendungsseite-Flips zu synchronisieren. Zumindest unter Windows ist das einfach falsch - ich habe Spiele geschrieben (mit denen ich Dinge auf einer ähnlichen Ebene wie das 15-Puzzle meine), die das tun. Ich habe mal etwas Zeit damit verbracht, mit Dark Basic und dem Dark GDK zu spielen - sowohl DirectX-basiert als auch beide synchronisierenden Seiten-Flips zum vertikalen Rücklauf im gefensterten Modus.

Antwort

4

Haupt bearbeitet

Es stellt sich heraus, dass ich, bevor er fragt mehr Zeit damit verbracht gesucht haben sollte. Aus der SDL FAQ ...

http://sdl.beuc.net/sdl.wiki/FAQ_Double_Buffering_is_Tearing

Das scheint ziemlich stark zu implizieren, dass mit dem vertikalen Rücklauf Synchronisierung nicht in SDL Fenster-Modus-Anwendungen unterstützt wird.

Aber ...

Die grundlegende Technik ist möglich auf Windows, und ich fange an, die denken SDL tut es, in gewissem Sinne. Nur noch nicht ganz sicher.

Unter Windows, sagte ich vorher, war das Synchronisieren von Seitenwechsel zu vertikalen Synchronisierungen im Fenstermodus bis zu den 16-Bit-Tagen mit WinG möglich. Es stellt sich heraus, dass das nicht genau falsch, aber irreführend ist. Ich habe mit WinG einen alten Quellcode ausgegraben, und es gab einen Timer, der die Seitenblitze auslöst. WinG wird mit irrwitziger Geschwindigkeit laufen, genau wie ich von SDL überrascht wurde - die Blit-to-Screen-Seitenwechseloperationen warten nicht auf für einen vertikalen Rücklauf.

Bei weiterer Untersuchung - wenn Sie eine Blit auf dem Bildschirm in WinG machen, wird die Blit für später in die Warteschlange gestellt und der Anruf beendet. Das Blit wird beim nächsten Vertikalrücklauf ausgeführt, also hoffentlich kein Reißen. Wenn Sie weitere Blits auf dem Bildschirm (schmutzige Rechtecke) vor diesem Rücklauf ausführen, werden sie kombiniert. Wenn Sie vor dem vertikalen Rücklauf viele Vollbild-Blits ausführen, werden Frames gerendert, die nie angezeigt werden.

Diese Blit-to-Bildschirm in WinG ist offensichtlich ähnlich wie die SDL_UpdateRect. SDL_UpdateRects ist nur eine optimierte Methode, um einige schmutzige Rechtecke manuell zu kombinieren (und sicher zu sein, dass sie auf den gleichen Frame angewendet werden). Also vielleicht (auf Plattformen, wo vertikale Rückverfolgung möglich ist) wird es in SDL gemacht, ähnlich wie in WinG - kein Warten, aber auch kein Zerreißen.

Nun, ich habe mit einem Timer getestet, um die Frame-Updates auszulösen, und das Ergebnis (unter Windows XP) ist unsicher. Ich könnte sehr leicht und gelegentlich an meinem alten Laptop zerreißen, aber das ist vielleicht kein Fehler von SDLs - es könnte sein, dass das "Raster" das Blit überholt. Dies ist wahrscheinlich meine Schuld für die Verwendung von SDL_Flip anstelle eines direkten Aufrufs von SDL_UpdateRect mit einem minimalen schmutzigen Rechteck - obwohl ich in diesem Fall versucht habe, zu reißen, um zu sehen, ob ich es könnte.

Also ich bin immer noch unsicher, aber es kann sein, dass Fenster-Modus-SDL ist so immun gegen Tearing wie es auf den Plattformen sein kann, die es erlauben. Die Ergebnisse scheinen nicht so schlecht zu sein, wie ich es mir vorgestellt habe, sogar auf meinem alten Laptop.

Aber - kann jemand eine definitive Antwort anbieten?

+0

Akzeptiert, um diese alte Frage zu schließen, aber ich bin noch offen für den Wechsel, wenn eine definitive Antwort erscheint. – Steve314

0

Sie können das Framerate-Steuerelement von SDL_gfx verwenden. am docs der Bibliothek sucht, wird der Fluss Ihrer Anwendung so aussehen:

// initialization code 
FPSManager *fpsManager; 
SDL_initFramerate(fpsManager); 
SDL_setFramerate(fpsManager, 60 /* desired FPS */); 


// in the render loop 
SDL_framerateDelay(fpsManager); 

Auch Sie am source code aussehen kann Ihr eigenes Framerate-Steuerelement zu erstellen.

+0

Die Frage ist, wie man Frames mit dem vertikalen Rücklauf synchronisiert. Die Analogie sind die alten CRT-Anzeigen, die den Rahmenwechsel mit einer Zeit synchronisieren, als der CRT-Strahl ausgeschaltet war. Bei modernen Displays gibt es keinen Strahl, aber es ist immer noch wichtig, mit vertikalem Rücklauf zu synchronisieren, um "[reißend] (http://en.wikipedia.org/wiki/Screen_tearing)" zu vermeiden. Das Einstellen einer Bildrate ist davon unabhängig - selbst wenn die Bildraten perfekt übereinstimmen, bedeutet das nur, dass sich der Riss in jedem Bild an derselben Position befindet. – Steve314

+0

TBH, meine letzte vorläufige Schlussfolgerung war, dass SDL * immer * mit vertikalem Rücklauf synchronisiert, wenn es dazu in der Lage ist. Es kann möglicherweise nicht im Fenstermodus sein. Es ist * möglich * - DirectX-Spiele im Fenstermodus tun das ständig - aber das bedeutet nicht, dass SDL sie unterstützen kann, und es kann davon abhängen, welche API SDL verwendet. – Steve314

+0

Ok. Ich denke, dass SDL dazu noch keine Möglichkeit hat. Wie auch immer, es muss einen Weg geben, es zu tun. GLFW führt VSync im Fenstermodus unter Windows aus. –