2009-08-29 16 views
5

Per effettuare il porting del mio gioco su iPhone, sto provando a creare un ciclo di gioco che non usi NSTimer.Come creare un ciclo di gioco sull'iPhone senza utilizzare NSTimer

ho notato in alcuni esempi di codice che, se si utilizza NSTimer, devi configurarlo a inizio con qualcosa di simile

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

dove drawView sarebbe simile:


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

Quando usando questa tecnica mFooModel si presenta bene, ma io invece voglio creare il mio loop di gioco che chiama drawView invece di avere NSTimer call drawView 60 volte al secondo. Vorrei qualcosa tipo:


while(gGameState != kShutDown) 
{ 
    [self drawView] 
} 

Sfortunatamente quando lo faccio, tutto quello che ottengo è uno schermo nero. Perché succede? Posso comunque implementare ciò che sto descrivendo qui?

Il motivo per cui voglio evitare NSTimer è perché voglio fare gli aggiornamenti di fisica e AI nel ciclo di gioco. Io uso il mio orologio/timer per tenere traccia della quantità di tempo che è trascorso in modo che io possa farlo con precisione. Il rendering avviene il più velocemente possibile. Io cerco di usare alcune delle tecniche descritte in this article

Questo è in qualche modo di una questione impulsiva (quello che si fa dopo che hai la codifica tutto il giorno, si blocca, e la speranza la risposta è lì da mattina)

Ciao ragazzi.

risposta

2

Se non si desidera utilizzare NSTimer si può provare l'esecuzione del NSRunLoop manualmente:

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

Grazie. Questo è un codice molto utile. – user156848

+0

Ho dimenticato di avvertire che se hai più lavoro di 1/45esimo di secondo (o le bancarelle di runloop per più di questo) avrai degli eventi tattili di balbuzie, ritardi e altri problemi dispari. Assicurati di testare accuratamente. Aggiornare il codice per renderlo possibile, ma specifico dell'applicazione – rpetrich

+0

Non tutto l'alloc/dealloc nel ciclo di esecuzione influisce sulle prestazioni? C'è un modo per spostare tutto fuori dal circuito? – Andrew

21

Un'altra opzione con iPhoneOS 3.1 è quello di utilizzare la nuova API CADisplayLink. Questo chiamerà il selettore specificato quando il contenuto dello schermo deve essere aggiornato.

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(renderAndUpdate)]; 
[displayLink setFrameInterval:2]; 
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

Il nuovo modello di progetto OpenGL in XCode utilizzare anche il CADisplayLink se avete bisogno di un po 'di codice di esempio.

+0

Devo aggiungere NSAutoreleasePool per displaylink –

+0

NSAutoreleasePool non è necessario. Crea un nuovo progetto basato su OpenGL in XCode e vedrai come usarlo. –

2

Mentre utilizzare CADisplayLink è un'alternativa molto valida per i giochi basati su 3.1,
qualsiasi cosa che usi "Timer" è una pessima idea.

L'approccio migliore è il buon vecchio "buffering tripple" per disaccoppiare il lavoro della GPU.

Fabien ha una spiegazione molto buona nella sua recensione Doom Iphone:
http://fabiensanglard.net/doomIphone/

0

Per quanto riguarda CADisplayLink e Doom per iPhone articolo di Fabien, ho mandato Fabien e penso che l'opzione migliore è soggettivo. DisplayLink e triplo buffering per prestazioni dovrebbero essere uguali, ma DisplayLink è disponibile solo su> OS 3.1. Questo dovrebbe essere il tuo fattore determinante.

2

Fare attenzione con self come destinazione per displayLinkWithTarget, il manuale dice "Il collegamento di visualizzazione appena costruito mantiene la destinazione". Martin