iphone - garageband - juegos apple gratis
Juegos iOS y gestión Run-Loop (1)
Para mis propios proyectos de iOS, utilizo el enfoque clásico (crear una ventana .nib, crear una clase que hereda EAGLView
, agregar EAGLView
a una vista en un controlador de vista que se coloca en su propio .nib).
En el trabajo, tomé un enfoque ligeramente diferente inspirado en SDL, que puedes inspeccionar en nuestra biblioteca de fuentes abiertas, APRIL . El objetivo principal de APRIL es admitir tantas plataformas como sea posible, manteniendo la simplicidad (solo administración de ventanas y entradas) y tener claridad sobre los problemas de licencia y la libertad de uso. Nuestros desarrolladores quieren escribir aplicaciones en una plataforma (Windows, Mac o Linux, de acuerdo con los gustos y deseos) y luego el código me es entregado para adaptarlo a otras plataformas.
En el enfoque que utilizamos en ABRIL, no crea ningún .nibs, y al llamar a UIApplicationMain
, especifica la clase de delegado como su cuarto argumento. El código de juego principal permanece absolutamente igual para cada plataforma, y solo las cosas específicas de la plataforma son #ifdef
''d en el código, o abstraídas en una biblioteca auxiliar.
En el delegado de la aplicación, usted crea el controlador de vista y la ventana:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// create a window.
// early creation so Default.png can be displayed while we''re waiting for
// game initialization
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// viewcontroller will automatically add imageview
viewController = [[AprilViewController alloc] initWithWindow:window];
[viewController loadView];
// set window color
[window setBackgroundColor:[UIColor blackColor]];
// display the window
[window makeKeyAndVisible];
// thanks to Kyle Poole for this trick
// also used in latest SDL
// quote:
// KP: using a selector gets around the "failed to launch application in time" if the startup code takes too long
// This is easy to see if running with Valgrind
[self performSelector:@selector(runMain:) withObject:nil afterDelay:0.2f];
}
¿Observe cómo demoramos el lanzamiento por 0.2? Es por eso que menciono la vista de imagen de arriba. Durante esos 0.2 segundos, tendríamos una pantalla en blanco que se muestra inmediatamente después de Default.png, y se presenta un retraso adicional antes de que el control se transfiera a runMain :, que libera el control a la aplicación principal:
- (void)runMain:(id)sender
{
// thanks to Kyle Poole for this trick
char *argv[] = {"april_ios"};
int status = april_RealMain (1, argv); //gArgc, gArgv);
#pragma unused(status)
}
Entonces, ahora el control nunca se transfiere al bucle principal real de UIApplication. Luego creas tu propio ciclo principal.
void iOSWindow::enterMainLoop()
{
while (mRunning)
{
// parse UIKit events
doEvents();
handleDisplayAndUpdate();
}
}
void iOSWindow::doEvents()
{
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while(result == kCFRunLoopRunHandledSource);
}
(En una nota lateral, se usa el controlador de vista, por supuesto, para simplificar la rotación de la interfaz de usuario para que coincida con la orientación del dispositivo).
Ambos enfoques utilizan CADisplayLink
si el sistema operativo lo admite. No he notado ningún problema con ninguno de los métodos, aunque mis proyectos privados se basan principalmente en acelerómetros. Sospecho que el enfoque de ABRIL podría hacer que algunos de los problemas desaparezcan también.
Primero, mi pregunta: ¿cómo gestionas tu iOS Run-Loop?
A continuación mi razón: he estado investigando esto con una variedad de prototipos (v. Desarrollo de la etapa inicial) y he encontrado una serie de problemas desconcertantes.
- Primero, los problemas de entrada y el ciclo de ejecución me llevan a probar lo siguiente:
- cuando uso el sistema más recomendado (CADisplayLink) noté que ciertas entradas táctiles se eliminan una vez que la carga de la CPU hace que la tapa del búfer (presentRenderBuffer) tenga que esperar un cuadro. Esto ocurre solo en el dispositivo y no en el simulador (molestamente, esto parece estar relacionado con esperar el bloqueo vsync en el hilo principal y la forma en que el proceso de ejecución de la aplicación toca la entrada y come los mensajes)
- cuando uso el siguiente sistema más recomendado (NSTimer) noté que ciertas entradas táctiles se eliminan una vez que la carga de la CPU alcanza cierto punto en el simulador pero no en el dispositivo (también de manera molesta). NSTimer también da como resultado una precisión mucho menor cuando mis actualizaciones se disparan
- cuando utilizo el sistema menos recomendado (ejecutando el bucle de ejecución en su propio subproceso administrado internamente con un temporizador de alta precisión construido desde mach_absolute_time, todos mis problemas de entrada táctil desaparecen, sin embargo, mi código ASSERT ahora atrapa el hilo equivocado y solo si duermo) después de la interrupción del software. (Mi código de afirmación es similar a http://iphone.m20.nl/wp/?p=1 ) Me gusta mucho tener mi trampa de código de afirmación inmediatamente en la línea que causó el problema, por lo que esta solución es no es realmente viable para mí: más difícil de depurar.
- Segundo, tiempo perdido:
- mientras investigaba el sistema, descubrí que independientemente del framerate (extrañamente, pero supongo que estadísticamente todavía tiene sentido con vsync) estoy esperando aproximadamente el 22% del tiempo en el vsync. Lo he confirmado moviéndome glFlush / glFinish y jugando con la frecuencia con la que hago las llamadas de PresentBuffer. Este es el momento clave en el que me encantaría procesar IA, etc. en lugar de limitarme a bloquear una llamada gl. La única forma en que puedo pensar en esto sería mover la renderización a su propio hilo, pero no estoy seguro de si está justificado comenzar a volver a diseñar para multi-threading en un dispositivo de un solo procesador.
Entonces, ¿alguien ha encontrado una solución mágica para estos problemas? ¿Alguien tiene una arquitectura de bucle de ejecución arrolladora que es genial en esta plataforma? Por el momento parece que tengo que elegir el menor de los males.