28 votes

Jeux iOS et gestion de la boucle d'exécution

Tout d'abord, ma question: Comment gérez-vous votre iOS de l'Exécution de la Boucle?

À côté de ma raison: j'ai fait des recherches ce avec une variété de prototypes (v. stade précoce de développement) et ont trouvé un certain nombre de problèmes qui rendaient perplexe.

  • Tout d'abord, d'entrée de questions et l'exécution de la boucle de me conduire à essayer ce qui suit:
    • lors de l'utilisation la plus recommandée pour le système (CADisplayLink) j'ai noté que certaines des entrées tactiles sont supprimés une fois que la charge CPU causes de la mémoire tampon flip (presentRenderBuffer), avoir à attendre un cadre. Cela se produit uniquement sur l'appareil et non dans le simulateur (fâcheusement - ce qui semble être liée à attendre vsync blocage sur le thread principal et le moyen de l'application d'exécution de la boucle du processus de saisie tactile & mange des messages)
    • lors de l'utilisation la plus recommandée pour le système (NSTimer) j'ai noté que certaines des entrées tactiles sont supprimés une fois que la charge CPU atteint un certain point dans le simulateur, mais pas dans l'appareil (aussi fâcheusement). NSTimer également des résultats en beaucoup plus faible précision lors de mes mises à jour de l'incendie
    • lors de l'utilisation de la moins recommandée pour le système (l'exécution de l'exécuter en boucle dans son propre thread géré à l'interne avec une haute précision de la minuterie construit à partir de mach_absolute_time, tous mes contact d'entrée problèmes disparaissent, cependant AFFIRMER mon code maintenant les pièges dans le mauvais thread et que si je usleep la suite de l'interruption logicielle. (Affirmer mon code est similaire à http://iphone.m20.nl/wp/?p=1) j'aime avoir mes affirmer code piège immédiatement à la ligne qui a provoqué le problème, donc cette solution n'est pas vraiment réalisable pour moi: plus difficile à déboguer.
  • Deuxièmement, le temps perdu:
    • alors qu'il enquête sur le système, j'ai constaté que, indépendamment de framerate (bizarrement, mais je suppose que statistiquement il a encore un sens w/vsync) je suis en attente d'environ 22% du temps sur la vsync. J'ai confirmé cela en se déplaçant autour de la glFlush/glFinish et en jouant avec la façon dont souvent je ne le presentRenderBuffer appels. C'est la clé du temps que j'aimerais être le traitement de l'IA, etc plutôt que de simplement caler sur un blocage gl appel. La seule façon que je peux penser autour de ce passerait rendu dans son propre thread, mais je ne sais pas si c'est justifié pour commencer à re-création de l'architecture multi-threading sur un seul processeur de l'appareil.

Si quelqu'un a trouvé une solution magique autour de ces questions? Quelqu'un aurait-il un tueur de l'exécution de la boucle de l'architecture qui est kick-ass sur cette plate-forme? Au moment où il regarde comme je dois choisir le moindre des maux.

6voto

Ivan Vučica Points 5418

Pour ma part iOS projets, j'utilise l'approche classique (créer une fenêtre .plume, créer une classe héritant EAGLView, ajoutez - EAGLView pour un affichage dans une vue-contrôleur qui est placé dans son propre .nib).

Au travail, j'ai pris une approche légèrement différente inspirée par SDL, que vous pouvez inspecter dans notre opensourced bibliothèque, AVRIL. Le but principal de l'APRIL, est de prendre en charge de nombreuses plates-formes que possible, tout en conservant la simplicité (et la fenêtre de gestion des intrants uniquement) et d'être clair sur les questions de licences et libre d'utilisation. Nos développeurs veulent écrire des applications sur une plate-forme (Windows, Mac ou Linux, selon les goûts et les désirs) et que le code est remis à m'adapter pour d'autres plates-formes.

Dans la méthode que nous utilisons en AVRIL, vous ne créez pas de tout .des plumes, et sur convocation UIApplicationMain, vous spécifiez le délégué de classe comme quatrième argument. Code principal de jeu reste absolument le même pour chaque plate-forme, et la seule plate-forme spécifique des choses est - #ifdef'd dans le code, ou abstraits dans une bibliothèque d'aide.

Dans l'app delegate, vous créez la vue et le contrôleur de la fenêtre:

- (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];
}

Notez comment nous retarder le lancement de 0,2? C'est pourquoi je le mentionne d'affichage de l'image ci-dessus. Au cours de ces 0,2 secondes, nous aurions vide de l'écran affiche immédiatement après le Défaut.png, et de délai supplémentaire est introduit avant le contrôle est transféré à runMain:, ce qui libère de contrôle de l'application principale:

- (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)
}

Alors, maintenant, le contrôle n'est jamais transférée de nouveau à UIApplication réels de la boucle principale. Ensuite, vous créez votre propre boucle principale.

    void iOSWindow::enterMainLoop()
    {
            while (mRunning) 
            {
                    // parse UIKit events
                    doEvents();
                    handleDisplayAndUpdate();
            }
    }

    void iOSWindow::doEvents()
    {
            SInt32 result;
            do {
                    result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
            } while(result == kCFRunLoopRunHandledSource);
    }

(Sur une note de côté, vue-contrôleur est utilisé, bien sûr, pour simplifier la rotation de l'INTERFACE utilisateur pour correspondre orientation de l'écran.)

Ces deux approches s'appuient CADisplayLink si prise en charge par le système d'exploitation. Je n'ai pas remarqué de problèmes avec l'une des méthodes, bien que mes projets privés sont principalement accéléromètre base. Je la soupçonne d'AVRIL approche pourrait rendre certains des problèmes de s'en aller, trop.

3voto

Joe Blow Points 3618

Vous avez évidemment d'experts de la compréhension de l'animation et de blitting en général, donc, je ne sais pas si c'est beaucoup plus d'une réponse pour vous en termes de iOS problème, mais:

"La seule façon que je peux penser autour de ce passerait rendu dans son propre thread, mais je ne sais pas si c'est justifié pour commencer à re-création de l'architecture multi-threading sur un seul processeur de l'appareil"

Je voudrais juste peut-être suggérer que: c'est monnaie courante et, err, idiomatiques, à bugger sur avec des processus d'arrière-plan dans iOS, en dépit de l'existence de 1x processeur. Je suis seulement capable de parler en termes généraux par rapport à vos très bonnes connaissances techniques spécifiques, mais la situation semble être que les ingénieurs de chez Apple faire de l'ensemble de cacao, runloop milieu plus compliqué la solution dans leur tête pour le "type de problème que vous décrivez semble être ... ", les développeurs devraient fond des choses".

Par exemple, si vous regardez cette autre question Mystérieux "ralentissement progressif" problème dans l'exécution de la boucle / drawRect.

et en particulier l'examen de la sortie d'exemple, près du fond, vous pouvez voir la "pause insérée par le système d'exploitation" sont la suite une sorte de dynamique de modèle (il y a certaines heuristiques passe là-bas, dans une tentative de la part des ingénieurs de chez Apple, comme c'était le cas, utilement le temps de partager autour) bien que l'heuristique est un mystère et, en effet, personne n'a été en mesure de déterminer exactement à quel stade de l'attente qui se passait.

Je n'ai appris à propos des threads et de l'activité en arrière-plan sur iOS, un peu, euh, il y a quelques heures. Heureusement, le tout est trivial sur iOS, il n'est pas comme sur lisa. Ainsi, lorsque vous dites: "je ne sais pas si c'est justifié pour commencer à re-création de l'architecture multi-threading", mon point est, il est plus ou moins complètement trivial et, comme je tente de l'exprimer, idiomatiques et ce que l'iOS d'ingénieurs "voulez vous faire".

Ainsi, par exemple, avec le problème en question, alors qu'elle reste totalement mystérieux (Un), précisément là où l'attente se passe et (B) quelle heuristique ils utilisent pour essayer d'aider, en fait nous avons juste peluche toute sorte de traitement possible dans les threads d'arrière-plan, PGCD, etc, et ça marche super. (Nous faisons les choses comme le traitement visuel si sont généralement de broyage de suite sur le processeur, l'interface m'agace!)

Je suppose que le point est, j'ai trouvé la semi-finition différente sur iOS (plus simple (trivial) - plus omniprésent, idiomatiques) que celui de Papa environnements, - peut-être que c'est quelque chose de réponse à votre question.

Par exemple: en faisant quelque chose de travailler à la fois sur un manycore mac et un ipad, je me suis retrouvé à l'aide de différentes approches: sur l'ipad, c'est "jeter des choses dans le fond pour éviter le type de manière générale, le problème que vous décrivez", alors que sur les processeurs multicœurs mac, c'est plus le concept traditionnel d'accélérer le travail via le parallélisme.

Ainsi, vous pouvez trouver cela inutile ou pas.

Une méta-réponse: si vous êtes nouveau à iOS, je vous invite à passer un DTS sur cette. (c'est à dire e-mail d'apple et de leur demander.) Si vous pouvez obtenir le droit d'ingénieur de chez Apple, ils sont fabuleux. (Vous pouvez ainsi obtenir un salaire minimum, ingénieur au premier abord, je pense qu'ils l'écran des questions de newbie de cette façon. Seulement se plaindre que vous voulez le patron et vous pouvez ainsi obtenir une réponse incroyable pour le type de vraiment avancé question que vous pose la question ici.)

"Si quelqu'un a trouvé une solution magique autour de ces questions?" ma solution de la semaine dernière est d'ignorer le problème, passez à la "iOS flux" et le fond de tout.

Peut-être cette randonnée permettra en quelque sorte!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X