2009-08-29 8 views
5

Para abrir mi juego al iPhone, intento hacer un bucle de juego que no use NSTimer.Cómo hacer un bucle de juego en el iPhone sin usar NSTimer

me di cuenta de algún código de ejemplo que, si se utiliza NSTimer, lo haces con ella al comienzo con algo como

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

donde drawView sería algo como:


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

Cuando Usando esta técnica, mFooModel funciona bien, pero en cambio quiero hacer mi propio bucle de juego que llama a drawView en lugar de tener NSTimer call drawView 60 veces por segundo. Me gustaría algo como:


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

Desafortunadamente cuando hago esto, todo lo que obtengo es una pantalla en negro. ¿Por qué pasó esto? ¿Hay alguna forma de implementar lo que estoy describiendo aquí?

La razón por la que quiero evitar NSTimer es porque quiero hacer actualizaciones físicas y de inteligencia artificial en el bucle del juego. Utilizo mi propio reloj/temporizador para hacer un seguimiento de la cantidad de tiempo que ha transcurrido para poder hacer esto con precisión. La representación ocurre lo más rápido posible. Trato de usar algunas de las técnicas que se describe en this article

Esto es algo así como una pregunta impulsiva (el que se hace después de que ha estado codificando todo el día, se atascan, y esperar la respuesta está allí por la mañana)

Saludos chicos.

Respuesta

2

Si no desea utilizar NSTimer puede intentar ejecutar la 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

Gracias. Este es un código muy útil. – user156848

+0

Olvidé advertir que si tienes más trabajo que una 1/45 de segundo (o los puestos de Runloop por más de eso) tendrás tartamudeos, eventos táctiles retrasados ​​y otros problemas extraños. Asegúrate de probarlo a fondo. Es posible actualizar el código para contabilizar eso, pero la aplicación específica – rpetrich

+0

¿No afecta todo el alloc/dealloc en el ciclo de ejecución al rendimiento? ¿Hay alguna manera de mover todo fuera del circuito? – Andrew

21

Otra opción con iPhoneOS 3.1 es utilizar la nueva API CADisplayLink. Esto llamará al selector que especifique cuando los contenidos de la pantalla necesiten actualizarse.

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

La nueva plantilla de proyecto de OpenGL en XCode también utilizan el CADisplayLink si necesita algo más de código de ejemplo.

+0

Necesito agregar NSAutoreleasepool para displaylink –

+0

NSAutoreleasepool no es necesario. Cree un nuevo proyecto basado en OpenGL en XCode y verá cómo usarlo. –

2

Durante el uso de CADisplayLink es una muy buena alternativa para juegos basados ​​en 3.1,
cualquier cosa que use "Timer" es una muy mala idea.

El mejor enfoque es el buen "buffering triple" para desacoplar el trabajo de la GPU.

Fabien tiene una muy buena explicación en su revisión del Destino Iphone:
http://fabiensanglard.net/doomIphone/

0

En cuanto CADisplayLink y el artículo de la condenación para el iPhone de Fabien, escrito que Fabien y creo que la mejor opción es subjetiva. Performance-wise DisplayLink y triple buffering deben ser iguales, pero DisplayLink solo está disponible en> OS 3.1. Entonces ese debería ser tu factor determinante.

2

Tenga cuidado al utilizar self como destino para displayLinkWithTarget, el manual dice "El enlace de pantalla recién construido conserva el objetivo". Martin

Cuestiones relacionadas