2009-08-29 3 views
5

Um mein Spiel sauber auf das iPhone zu portieren, versuche ich eine Spielschleife zu erstellen, die NSTimer nicht verwendet.Wie mache ich eine Spielschleife auf dem iPhone, ohne NSTimer zu verwenden

bemerkte ich in einigen Beispielcode, der bei Verwendung von NSTimer, können Sie es bis zu Beginn mit etwas gesetzt hatte wie

self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES]; 

wo drawView würde in etwa so aussehen:


- (void)drawView 
{ 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); 
    mFooModel->render(); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 
} 

Wenn mit dieser Technik rendert mFooModel gut, aber ich möchte stattdessen meine eigene Spielschleife erstellen, die drawView aufruft, anstatt NSTimer call drawView 60 mal pro Sekunde zu haben. Ich möchte so etwas wie:

Leider, wenn ich das tue, bekomme ich nur einen schwarzen Bildschirm. Warum passiert das? Kann ich das was ich hier beschreibe implementieren?

Der Grund, warum ich NSTimer vermeiden möchte, ist, weil ich Physik und AI Updates in der Spielschleife machen will. Ich benutze meine eigene Uhr/Timer, um die Zeit zu verfolgen, die verstrichen ist, damit ich das genau machen kann. Das Rendern erfolgt so schnell wie möglich. Ich versuche, einige der Techniken, wie beschrieben zu verwenden this article

Dies ist etwas von einer impulsiven Frage (die, die Sie tun, nachdem Sie den ganzen Tag habe Codierung, stecken bleiben, und hoffen, dass die Antwort ist dort bis zum Morgen)

Prost Jungs.

Antwort

2

Wenn Sie nicht verwenden NSTimer möchten, können Sie versuchen, die NSRunLoop manuell ausgeführt wird:

static BOOL shouldContinueGameLoop; 
static void RunGameLoop() { 
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; 
    NSDate *destDate = [[NSDate alloc] init]; 
    do { 
     // Create an autorelease pool 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     // Run the runloop to process OS events 
     [currentRunLoop runUntilDate:destDate]; 
     // Your logic/draw code goes here 
     // Drain the pool 
     [pool drain]; 
     // Calculate the new date 
     NSDate *newDate = [[NSDate alloc] initWithTimeInterval:1.0f/45 sinceDate:destDate]; 
     [destDate release]; 
     destDate = newDate; 
    } while(shouldContinueGameLoop); 
    [destDate release]; 
} 
+0

Danke. Dies ist ein sehr nützlicher Code. – user156848

+0

Ich habe vergessen zu warnen, dass, wenn Sie mehr Arbeit als 1/45. einer Sekunde haben (oder der Runloop für mehr als das hält) Sie Stottern, verzögerte Berührungsereignisse und andere seltsame Probleme haben werden. Seien Sie sicher, gründlich zu prüfen. Aktualisieren des Codes, um dies zu berücksichtigen, ist möglich, aber anwendungsspezifisch – rpetrich

+0

Beeinträchtigt nicht die gesamte alloc/dealloc in der Ausführungsschleife die Leistung? Gibt es eine Möglichkeit, das alles außerhalb der Schleife zu bewegen? – Andrew

21

Eine weitere Option mit iPhoneOS 3.1 ist die neue CADisplayLink api zu verwenden. Dadurch wird der von Ihnen angegebene Selektor aufgerufen, wenn der Bildschirminhalt aktualisiert werden muss.

Die neue OpenGL-Projektvorlage in XCode verwendet auch den CADisplayLink, wenn Sie mehr Beispielcode benötigen.

+0

Muss ich NSAutoreleasePool für Dispaylink hinzufügen –

+0

NSAutoreleasePool ist nicht erforderlich. Erstellen Sie ein neues OpenGL-basiertes Projekt in XCode und Sie werden sehen, wie Sie es verwenden. –

2

Während der Verwendung von CADisplayLink ist eine wirklich gute Alternative für 3.1 basierte Spiele,
alles mit "Timer" ist eine wirklich schlechte Idee.

Der beste Ansatz ist die gute alte "Tripple-Pufferung", um die GPU-Arbeit zu entkoppeln.

Fabien eine sehr gute Erklärung in seiner Doom Iphone Bewertung hat:
http://fabiensanglard.net/doomIphone/

0

In Bezug auf CADisplayLink und die Doom für iPhone Artikel von Fabien, mailte ich Fabien und ich denke, die beste Option subjektiv ist. Leistungsmäßig sollten DisplayLink und Triple Buffering gleich sein, aber DisplayLink ist nur unter> OS 3.1 verfügbar. Das sollte dein bestimmender Faktor sein.

2

Seien Sie vorsichtig mit self als Ziel für displayLinkWithTarget, das Handbuch sagt "Die neu konstruierte Display-Link behält das Ziel". Martin

Verwandte Themen