2009-03-13 4 views
2

Ich habe Probleme beim Erstellen einer soliden Spielengine für meine OpenGL-Anwendung. Es ist ein Spiel, das aus mehreren Sprites mit einer Menge Action besteht.Eine solide (framerate stabile) Engine für OpenGL (ES) erstellen

Ich erstellte Objekte, die im Grunde alle meine Sprites sind. Ein anderes Objekt namens "gameEngine" durchläuft eine Reihe von Berechnungen jede Sekunde (ein Timer), was zu neuen Spielvariablen führt. Danach kennen die Sprite-Objekte ihre Zeichnungsdaten.

Das Problem ist, dass nach all meinen Zeichnungsdatum zu sammeln, die Zeichnung Ort genau im richtigen Moment in der Zeit nehmen soll, in einer stetigen Animation führt. Abhängig von der Komplexität der aktuellen Szene benötigen die Spielberechnungen eine unbestimmte Zeit. Die eigentliche Zeichnung findet also zu verschiedenen Zeitpunkten statt. Wie würde ich das verhindern?

Um zu klären, geht mein Ansatz so etwas wie:

// Every something of a second I call tick 
-(void)tick 
{ 
    drawingData = gameEngine(); 
    draw(drawingData); 
} 

Es muss für den Bau von Game-Engines wie dies eine bewährte Methode sein, ich bin nicht bewusst?

Antwort

0

Die beste Lösung wäre eine Multithread-Anwendung - ein Thread berechnet die Zeichnungsdaten in einen Puffer und ein Rendering der Daten.

Wenn Sie nach einer wirklich einfachen Lösung suchen, kehren Sie einfach die Reihenfolge von Berechnung und Rendering um.

void Initialize() 
{  
    DrawingData = GameEngine(); 
} 

void Tick() 
{ 
    Draw(DrawingData); 
    DrawingData = GameEngine(); 
} 

Sie berechnen die ersten Zeichnungsdaten beim Start der Anwendung und wenn der Timer ausgelöst wird, zeichnen Sie sie einfach. Danach haben Sie die Zeit bis zum nächsten Timer-Event, um die Zeichnungsdaten erneut zu berechnen.

Aber im Allgemeinen kann es eine bessere Lösung sein, mit einer variablen Bildrate zu rendern - Sie vermeiden die Probleme, wenn die Maschine für die gewünschte Bildrate verlangsamen und hohe Bildraten auf schnellen Maschinen bieten.

void Main() 
{ 
    StartTime = Now(); 

    while (!ExitRequested) 
    {  
     DrawingData = GameEngine(Now() - StartTime); 
     Draw(DrawingData); 
    } 
} 

Sie machen Rahmen so schnell wie möglich - nicht mit einem festen Intervall zwischen den einzelnen Bildern, sondern mit der Echtzeit wird die Anwendung ausgeführt wird. Das bedeutet, dass Sie Ihre Objekte nicht um 20 Millisekunden pro Frame vorrücken lassen, sondern verschieben Sie sie einfach an die Position, die die aktuelle Laufzeit angibt.

+3

Eigentlich eine feste Schritt Spiel-Schleife ist in der Regel die bevorzugte Option, wenn Sie etwas wirklich einfach programmieren. –

0

Es ist etwas plattformabhängig, aber ein grundlegender Ansatz, der normalerweise funktioniert, ist die Verwendung eines Hochleistungs-Timers in Ihrer Render-Schleife, der Ihnen hilft, zwischen Frames zu schlafen, um eine stabile, konstante Framerate zu erhalten.

Sie können das Rendering Ihres Frames zeitlich anpassen und dann um den Betrag schlafen, um eine stabile Framerate beizubehalten.

Wenn Ihre Plattform jedoch nicht mit der gewünschten Framerate mithalten kann, müssen Sie nach Möglichkeiten zur Optimierung Ihrer Game Engine suchen. Dies funktioniert nur, um Dinge zu verlangsamen, um sie konsistent und reibungslos zu machen - nicht um es zu beschleunigen.

--- Klärung ----

 
-(void)tick 
{ 
    time = now() // from high perf. timer 
    drawingData = gameEngine();

newTime = now() 
// pause for the time required to make the framerate consistent 
Sleep(totalTimeForTickToBeStable - newTime + time) 
draw(drawingData); 

}

1

Das ist wirklich nicht über OpenGL; Es handelt sich eher um die Betriebssystem- oder System-APIs, die Sie verwenden (z. B. Carbon/Cocoa/Win32). Aber die wirklich, wirklich einfache Fall ist der (Pseudo-Code):

checkTime = currentTime 
while not exitCondition 
    if currentTime - checkTime >= 50 milliseconds 
     checkTime = checkTime + 50 milliseconds 
     updateScene 
    else drawScene 

Sie sind so oft wie möglich zu zeichnen, aber nur tun, um die Updates alle 50 Millisekunden (das heißt 20-mal pro Sekunde). Es gibt natürlich eine Los von anderen Dingen zu denken, vor allem in Bezug auf das, was Sie tun, wenn Sie zurückfallen (Frames überspringen).

Der beste Platz in OpenGL Sachen zu bekommen, sind Nehe Lektionen:

http://nehe.gamedev.net/lesson.asp?index=01

Sie sind immer ein wenig altmodisch, aber der Beispielcode am Ende jeder Lektion ist ein großartiger Ort zu starten, und es ist in vielen Sprachen und für viele Betriebssysteme verfügbar.

6

Spielschleifen gibt es in vielen Varianten, aber die besseren trennen die Animation von der Zeichnung oder in einem klassischen Terminologiemodell und -ansicht. Im Grunde genommen möchten Sie ein Modell Ihres Spiels konstruieren, in dem Sie die verstrichene Zeit festlegen und das Modell aktualisieren (physikalische Framerate) und dann unabhängig voneinander einen Schnappschuss des Modells zu aufeinanderfolgenden Zeitpunkten rendern können (Rendering-Framerate).

Hier sind ein paar Artikel, die eine detailliertere Erklärung einiger Varianten von Spielschleifen und ihrer Vor- und Nachteile geben. Es gibt auch Quellcode. Ich hoffe, es hilft.

Fix Your Timestep! und deWiTTERS Game Loop Article

+1

Serious +1 für "Fix your Timestreet!". Dies ist ein Muss für jeden, der wirklich wissen möchte, wie Sie Ihre Spielschleife am besten gestalten. Es kann ein paar Lesevorgänge dauern, um es in der Art zu verstehen, wie es präsentiert wird, aber es ist wirklich sehr einfach. –