Random "pas si random que ça"

2»

Réponses

  • Philippe49Philippe49 Membre
    17:09 modifié #32
    dans 1246177838:

    et c'est quoi, au juste, un thread ?


    Ah là  si tu veux programmer, il va falloir apprendre cela, parce que c'est essentiel ...
    Wikipedia , google, .... ou un bon cours d'informatique ... En gros cela permet de lancer plusieurs tâches simultanément en parallèle et non séquentiellement.

    Dans la doc Apple, part de NSThread et du programming guide associé
  • vico92vico92 Membre
    17:09 modifié #33
    Bonjour,

    J'ai créé un nouveau thread pour exécuter le plus gros calcul de mon appli séparément, mais ça n'améliore pas la fluidité.

    Ce calcul doit être fait 60 fois /sec, alors j'ai essayé différentes constructions comme utiliser un timer, plutôt que d'implementer le calcul dans l'accelerometre. Ca ne change rien non-plus.

    J'ai lu l'article concernant l'openGL que tu as cité, Draken, j'essayerais bien de tout passer en openGL, mais ce dernier ne s'utilise que pour faire de la 3D, non ?

    Sinon, j'ai aussi lu qu'on pouvait/devait utiliser plusieurs delegate, je ne sais pas trop comment faire ça, mais est-ce que ça pourrait améliorer la fluidité selon vous ? (plusieurs delegate, ça revient au même que plusieurs threads ?)

    Bref, je suis un peu frustré de me retrouver bloqué dans le developpement de mon jeu à  cause de leaks, devant lequels je me sens bien incompetent...

    (je peux envoyer mon code complet en p.m. si qq1 a le coeur a y jeter un oeil pour voir ce qui cloche)

    Toute aide sera la bienvenue :)
    Vico
  • Philippe49Philippe49 Membre
    17:09 modifié #34
    Mais c'est quoi ton calcul horrible qui prend plus de temps que celui que je cite  :

    dans 1246174216:

    Pour donner une idée, dans Count It Right, les calculs des solutions sont faits par écriture dynamique de toutes les solutions. Cela peut représenter jusqu'à  20 Mo de zone mémoire allouée (j'ai mesuré, cela m'inquiétait quand même un peu). Temps d'exécution moyen ? moins d'un centième de seconde (pour 2Mo). Et pendant ce temps les animations graphiques ne sont pas ralenties.

    Je t'assure que 2 Mo de mémoire pour faire un calcul, c'est vraiment beaucoup.

    Tu peux montrer le code de ce calcul ?
  • DrakenDraken Membre
    17:09 modifié #35
    Pour répondre à  ta question, Vico92, OpenGL est conçu pour la 3D, mais la 2D n'est qu'une forme simplifiée de 3D ! En utilisant les bons paramètres, OpenGL peut dessiner dans un espace 3D "plat", de la taille de l'écran de l'iPhone.

    D'ailleurs, le template "OpenGL ES Application" du SDK iPhone active le mode .. 2D et non 3D comme on pourrait le penser ! L'exemple GLSprite d'Apple montre comment afficher une image en mode 2D.

    Mais à  mon avis, la solution à  ton problème n'est pas dans OpenGL. Ton jeu n'a pas l'air d'avoir besoin d'une grosse puissance de traitement. C'est probablement un problème d'architecture ou une mauvaise utilisation d'une fonction. Comme le dit Philippe, ce n'est pas normal que ton calcul prenne autant de temps.

    Les delegates n'ont rien a voir avec les threads. Tu devait lire ou relire le chapitre 6 de l'ouvrage "Programmation Cocoa sous Mac OSX" présentant les delegates.

    Si tu veux, envoie moi ton code. Mais je ne te garantis rien, je ne suis qu'un débutant en Objective-C, sans grande connaissance du graphisme en Cocoa, préférant m'attaquer directement à  OpenGL, dont la philosophie est proche de mes "habitudes" de programmation.

  • vico92vico92 Membre
    17:09 modifié #36
    hmmm... Je vais vous envoyer mon code cet aprem, je quitte le boulot vers 15h.

    Merci à  vs 2
    Vico
  • AliGatorAliGator Membre, Modérateur
    17:09 modifié #37
    dans 1246601989:
    J'ai créé un nouveau thread pour exécuter le plus gros calcul de mon appli séparément, mais ça n'améliore pas la fluidité.
    Normal, les threads ne sont pas conçus pour améliorer la fluidité, uniquement pour effectuer des traitements non bloquants en parallèle... mais ça a un coût, à  la fois celui du scheduling des divers threads et celui de la synchronisation. C'est pas nouveau, et c'est une grossière erreur (bien que malheureusement communément faite par les débutants) que de croire que les threads accélèrent une appli de manière générale.

    dans 1246601989:
    (plusieurs delegate, ça revient au même que plusieurs threads ?)
    Oulà  heu c'est quoi cette confusion là  ? Pfiou! Bon heu je vais pas te faire un cours, d'autant qu'osx-dev est pas à  vocation d'être un forum de débutants à  la base, mais y'a de la relecture de concepts de programmation à  faire là ...

    dans 1246601989:
    Bref, je suis un peu frustré de me retrouver bloqué dans le developpement de mon jeu à  cause de leaks
    Et qui te dit que ce sont des leaks ? Et pas plutôt un pb d'optimisation, ou de surcharge de requêtes de dessin ou autre ? Faut pas tout mélanger...
  • vico92vico92 Membre
    17:09 modifié #38
    dans 1246625319:

    Normal, les threads ne sont pas conçus pour améliorer la fluidité, uniquement pour effectuer des traitements non bloquants en parallèle...


    Je pensais qu'effectuer des traitements en parallele pouvait améliorer la vitesse l'execution.

    Merci pour tes autres conseils, je vais replonger dans mes bouquins ^^
  • AliGatorAliGator Membre, Modérateur
    17:09 modifié #39
    Effectuer des traitements en parallèle ne permet que... d'effectuer des traitements en parallèle. Mais pas pour autant, du moins dans l'absolu,  d'accélérer l'exécution...

    Bon, ok, c'est un peu drastique comme affirmation : bien sûr, avec les processeurs multi-coeurs, paralléliser diverses tâches sur les différents coeurs permet de décharger chaque coeur, et de terminer les exécutions desdites tâches plus tôt, plutôt que de les exécuter séquentiellement (donc d'attendre que la tâche 1 soit finie avant d'exécuter la tâche 2).

    Mais si je dis que ce n'est pas systématique, ce n'est pas pour rien : beaucoup pensent que créer un thread va magiquement accélérer le traitement de leur tâche. S'il n'y a qu'une seule tâche à  exécuter, l'exécuter dans le thread principal ou un thread séparé n'aura pas d'incidence, si ce n'est de libérer le thread principal qui est aussi en charge de gérer l'interface, la boucle d'événements, les boucles de composition et de rendu graphique... et donc exécuter ta tâche dans un thread principal va permettre de ne pas bloquer l'interface.

    Mais ce que je veux dire c'est que souvent beaucoup pensent que quand ils exécutent une tâche qui est longue et que ça bloque l'interface (alors qu'ils espéraient que leur barre de progression avance pendant la tâche), en mettant un thread ça va "accélérer" l'exécution de leur tâche (alors que pas du tout, au contraire même, puisqu'en plus de la tâche l'interface va se mettre à  jour donc ça prend un peu de temps même si c'est peu)

    Et puis de plus, utiliser les threads nécessite aussi d'avoir conscience des problématiques the Multithreading et de temps réel. A savoir les contraintes temps-réel si besoin (contraintes de fenêtre/temps d'exécution), mais surtout la synchronisation inter-threads, la protection de données (par des mutex ou @synchronize par exemple), et les risques de dead-locks.


    Enfin voilà , ne jamais faire une généralité de l'idée "je vais faire un thread ça va aller plus vite", c'est loin d'être aussi simple ni toujours vrai.
  • DrakenDraken Membre
    17:09 modifié #40
    Vico, j'ai jeté un regard rapide sur ton code. Et je vois un problème potentiel. Tu as réglé la fréquence d'échantillonnage de ton accéléromètre à  80 Hz, tout en insérant des calculs et un traitement graphique dans la routine de traitement des accélérations.

    Au final ton code est exécuté 80 fois par seconde, alors que l'écran iPhone/iTouch est rafraà®chi à  60 Hz. Sur le site de développement, Apple recommande d'utiliser 30 images/s pour les programmes graphiques (alors que les exemples officiels d'utilisation d'OpenGL iPhone tournent à  60 images. Enfin passons !).

    Essaie de diminuer la vitesse de ton accéléromètre pour voir ce que cela donne.

  • 17:09 modifié #41
    dans 1246644078:

    dans 1246625319:

    Normal, les threads ne sont pas conçus pour améliorer la fluidité, uniquement pour effectuer des traitements non bloquants en parallèle...


    Je pensais qu'effectuer des traitements en parallele pouvait améliorer la vitesse l'execution.

    Merci pour tes autres conseils, je vais replonger dans mes bouquins ^^


    Attention à  faire bien gaffe à  ça. créer un nouveau thread c'est utile par exemple sur des operations bloquantes. Quand par exemple tu veux charger un NSData via internet ça prend un certain temps à  cause de la connexion en plus.
    C'est pareil pour une énumération par exemple. Enumérer 100 000 objets ça prend du temps (même si les algos sont automatiquement adaptés), il est donc forcé que ton application "freeze" au moins 5 secondes.
    Je retourne sur mon NSData via internet car là  on se rend plus compte :
    Je cherche à  charger une image via internet : j'utilise NSData + UIImage.
    NSData -> -initWithContentsOfURL:
    Imagine que l'image pèse 1Mo.. bon ben ton code va se bloquer pendant x secondes, le temps qu'il faut pour charger l'image.

    Bon ben maintenant imagine que t'en a 50 à  charger? Tu vas t'amuser à  charger les 50 les unes à  la suite des autres? C'est là  encore que le thread est intéressant. Ton programme principale est un thread, tu en détaches un autre afin d'éviter de bloquer ton programme principale.
    Ainsi si Mr. X veut naviguer dans ton application pendant le chargement des images, il n'aura aucun problème.

    Au final ton programme n'est pas plus rapide.
  • Philippe49Philippe49 Membre
    17:09 modifié #42
    Oui 80 Hz c'est curieux. Il y a surtout dans la méthode accelerometer: didAccelerate: de multiples rafraichissements .
    • Quand tu fais secretView.layer.anchor=value; tu provoques un rafraichissement.
    • Puis quand tu fais secretView.transform=transformValue; de nouveau.
    • puis  secretView.center=aCenter; encore.
    ...

    Donc une dizaine de rafraichissements dans cette méthode appelée 80 fois par secondes, cela fait vraiment beaucoup. Essaie d'encadrer tout cela dans un [UIView beginAnimations: context:]  ... [UIView commitAnimations], tout devrait se faire en une seule fois.
  • DrakenDraken Membre
    17:09 modifié #43
    Chacune de ces opérations provoque un rafraà®chissement ! Outch ! Bon, pas la peine de chercher plus loin. Philippe a mis le doigt sur le problème. Pas étonnant que cela lague, avec des centaines de rafraà®chissements par seconde

    Maintenant je comprend pourquoi certains jeux de l'AppStore ont des scrollings aussi mauvais.

  • DrakenDraken Membre
    17:09 modifié #44
    Pour te consoler Vico, quelques planches 2D supplémentaires :


     
  • DrakenDraken Membre
    17:09 modifié #45
    Et :
  • Philippe49Philippe49 Membre
    17:09 modifié #46
    Je pense également que tu dois pouvoir améliorer la gestion de ta backgroundView.

    J'essaierais le CGImageCreateWithImageInRect() plutôt que de traà®ner une image view de 1400 sur 1000 .. à  voir


    Ensuite, 
    ratioAy = secretView.center.y/320; s'optimise en secretView.center.y*0.003125; (une mutiplication est plus rapide qu'une division) 
    bMinX = 1421*finalScale/2 - 480; s'écrit 710.5*finalScale-480.;
  • Philippe49Philippe49 Membre
    17:09 modifié #47
    Jolies les images, Draken ...
  • vico92vico92 Membre
    juillet 2009 modifié #48
    Essaie de diminuer la vitesse de ton accéléromètre pour voir ce que cela donne.


    J'ai essayé avec 60 et avec 30-> pas mieux
    et en-dessous de 30, c'est moins bon qu'à  80 (le scrolling du fond est parfois rapide et à  - de 30hz ça saccade par manque de fps)

    ...tout en insérant des calculs et un traitement graphique dans la routine de traitement des accélérations.



    Oui 80 Hz c'est curieux. Il y a surtout dans la méthode accelerometer: didAccelerate: de multiples rafraichissements .
    • Quand tu fais secretView.layer.anchor=value; tu provoques un rafraichissement.
    • Puis quand tu fais secretView.transform=transformValue; de nouveau.
    • puis  secretView.center=aCenter; encore.
    ...

    Donc une dizaine de rafraichissements dans cette méthode appelée 80 fois par secondes, cela fait vraiment beaucoup. Essaie d'encadrer tout cela dans un [UIView beginAnimations: context:]  ... [UIView commitAnimations], tout devrait se faire en une seule fois.


    J'utilise l'accelerometre comme un timer, en fait.
    Pour tester, ce soir j'ai externalisé les traitements graphiques dans des méthodes individuelles, appelées 60x/sec par l'accelerometre (car a part avec des timers reglés à  1/60 de sec, j'ai pas trop le choix pour rafraichir toutes les données d'animation) mais ce n'est pas mieux.


    Chacune de ces opérations provoque un rafraà®chissement ! Outch ! Bon, pas la peine de chercher plus loin. Philippe a mis le doigt sur le problème. Pas étonnant que cela lague, avec des centaines de rafraà®chissements par seconde


    bah voui mais j'ai besoin de ce rafraichissement si je veux pas que le jeu ressemble à  un diaporama !! Vous faà®tes comment, vous ?


    Essaie d'encadrer tout cela dans un [UIView beginAnimations: context:]  ... [UIView commitAnimations], tout devrait se faire en une seule fois.


    Les animations sont dynamiques, quand tu bouges l'iPhone, tu pilotes ton cerf-volant en temps réel, quand tu utilises le slider, tu change la valeur de zoom de l'ensemble, avec tous les calculs que ça induit derrière (taille, vitesse defilement, limites de position, etc)

    Je suis bien embêté avec cette histoire, moi, comment ça se fait qu'on voit plein de jeux hyper-complexes qui tournent tres bien, et moi j'ai 3 pauvres images, avec certes pas mal de calculs, mais quand-même...
    Je vois pas comment l'optimiser plus sans sacrifier certaines fonctionnalités essentielles, alors là  c'est la cata !!  :'(
  • vico92vico92 Membre
    juillet 2009 modifié #49
    dans 1246663408:

    Jolies les images, Draken ...


    Oui, c'est joli, et il me semble les connaà®tre ces persos, mais je retrouve pas le nom...

    Je pense également que tu dois pouvoir améliorer la gestion de ta backgroundView.

    J'essaierais le CGImageCreateWithImageInRect() plutôt que de traà®ner une image view de 1400 sur 1000 .. à  voir


    Ensuite, 
      ratioAy = secretView.center.y/320; s'optimise en secretView.center.y*0.003125; (une mutiplication est plus rapide qu'une division) 
      bMinX = 1421*finalScale/2 - 480; s'écrit 710.5*finalScale-480.;


    merci pour le tuyau, je savais pas que les / etait plus longues que les *, il faut que je change ça.

    Je vais essayer ton idee du CGImageCreateWithImageInRect(), ça ne calculera que la surface visible de l'image, et c pas bête du tout ça.

    merci pour votre expertise, les gars
    (mais si probleme persiste après ça, je vois pas quoi faire et ça me dégouterai d'avoir bossé comme un damné pour rien, qd-même... :'( )

    Bonne nuit
  • Philippe49Philippe49 Membre
    17:09 modifié #50
    dans 1246664313:

    Pour tester, ce soir j'ai externalisé les traitements graphiques dans des méthodes individuelles, appelées 60x/sec par l'accelerometre (car a part avec des timers reglés à  1/60 de sec, j'ai pas trop le choix pour rafraichir toutes les données d'animation) mais ce n'est pas mieux.

    Cela ne peut effectivement rien changer.


    dans 1246664313:

    bah voui mais j'ai besoin de ce rafraichissement si je veux pas que le jeu ressemble à  un diaporama !! Vous faà®tes comment, vous ?

    Tu encadres l'ensemble des changements dans la méthode de l'accéléromètre par [UIView beginAnimations: context:]  au début de la méthode et  [UIView commitAnimations] à  la fin.
    L'ensemble des changements est stocké dans l'animation comme état final à  atteindre et sont tous réalisés simultanément. Par contre je n'ai jamais essayé setAnimationDuration:0.01 avec d'aussi faibles valeurs.


    dans 1246664313:

    Les animations sont dynamiques, quand tu bouges l'iPhone, tu pilotes ton cerf-volant en temps réel, quand tu utilises le slider, tu change la valeur de zoom de l'ensemble, avec tous les calculs que ça induit derrière (taille, vitesse defilement, limites de position, etc)

    Si tu ne peux pas assumer tous les mouvements en simultané, et l'utilisateur ne va pas en même temps bouger le curseur et l'iphone, mets des verrous.
  • AliGatorAliGator Membre, Modérateur
    17:09 modifié #51
    Pour les multiplications au lieu des divisions, je suis sceptique.

    Non pas que les multiplications soient plus rapides que les divisions, ça c'est sûr et certain, une division prend plus de cycles processeur qu'une multiplication. Mais je suis quasiment sûr, étant donné que c'est en l'occurence une division par une constante (320 dans ton cas), que le compilateur gcc optimise tout ça automatiquement. Cela fait partie des optimisations de base qu'un compilo sait en général faire tout seul, et ça m'étonnerait fort que ce ne soit pas le cas de gcc.

    Et laisser le /320 au lieu du * 0.003125 permet de garder un code lisible plutôt que d'y introduire des magic numbers (qui sont à  proscrire)...

    Par contre pour le reste, effectuer des actions de rafraà®chissement hors de la boucle de composition, et encore pire dans des méthodes potentiellement appelées 80 fois par seconde (pourquoi mettre l'accéléromètre à  une fréquence aussi élevée que 80Hz, en plus?), faut pas chercher plus loin les raisons du lag.
  • Philippe49Philippe49 Membre
    17:09 modifié #52
    Ok pour la lisibilité, et pour le caractère infime du gain dans le cas de Vico, mais je confirme pour ce qui est du gain multiplication vs division , de l'ordre de 20 à  25% , en utilisant ou non une optimisation:

    <br />#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br /><br /><br />int main (void)<br />{ <br />	double x=1.0;<br />	int i;<br />	for(i=0;i&lt;10000000;i++) {<br />		x=random()/320;&nbsp; &nbsp; &nbsp; //*0.003125;<br />	}<br />	printf(&quot;%.2f&#092;n&quot;,x);<br />	return 0;<br />}<br />
    


    Execution

    % gcc pgm4.c -o pgm -O3  #avec la multiplication
    % time pgm
    583396.97

    real 0m0.069s
    user 0m0.065s
    sys 0m0.002s
    % gcc pgm4.c -o pgm -O3  #avec la division
    % time pgm
    583396.00

    real 0m0.089s
    user 0m0.086s
    sys 0m0.002s
    %



    Suivre le très intéressant post de Mala et son simulateur de particules
  • Philippe49Philippe49 Membre
    17:09 modifié #53
    dans 1246666469:

    Tu encadres l'ensemble des changements dans la méthode de l'accéléromètre par [UIView beginAnimations: context:]  au début de la méthode et  [UIView commitAnimations] à  la fin.
    L'ensemble des changements est stocké dans l'animation comme état final à  atteindre et sont tous réalisés simultanément. Par contre je n'ai jamais essayé setAnimationDuration:0.01 avec d'aussi faibles valeurs.

    Autrement tu peux aussi redéfinir les setter correspondants en sous-classant les views, en s'arrangeant pour que le setNeedsDisplay ne soit appelé qu'une fois uniquement.
  • vico92vico92 Membre
    juillet 2009 modifié #54
    Bonjour,

    Après une série de test visant à  repartir d'une version minimaliste du jeu (juste le cerf-volant, le fond et les poignées), en baissant la cadence de l'accelerometre à  1/30eme de sec, et en ajoutant les éléments "optionnels" du jeu petit à  petit, le lag apparaà®t lors de l'ajout d'une view contenant un drawRect avec conversion de coordonnées. En effet, cette methode me permettait de dessiner les fils qui relient le cerf-volant aux poignées, mais même en ne les redessinant qu'à  1/30 sec, ça créé une saccade très nette.

    Conclusions:

    1- Oui, une cadence de rafraichissement de 80hz est une idiotie
    2- Les calculs pour le decors de fond qui paraissent lourds sont en fait très bien gérés.
    3- C'est le [drawRectView setNeedDisplay]; qui passe pas.
    Trop compliqué pour lui de dessiner une ligne 30 fois par sec., je suis mdr
    De plus, le rafraichissement des lignes ne se fait pas durant les animations blocks (beginAnimations:context:) ce qui est aussi problematique

    Je vais donc me séparer de ces ficelles qui sont en fait des chaà®nes à  mon cou.

    Merci à  tous, 
    Vico
  • DrakenDraken Membre
    17:09 modifié #55
    Essaye de "ruser" en remplaçant le tracé des lignes par un affichage de sprites. Utilise un logiciel graphique pour fabriquer une image ne contenant qu'une ligne droite. Et affiche-la ensuite sur l'écran, en calculant la position de manière à  toucher le cerf-volant.

    C'est un peu étrange comme méthode, horriblement mal optimisée, mais ça devrait passer dans le beginAnimations:context. * croise les doigts *

  • vico92vico92 Membre
    17:09 modifié #56
    dans 1246732992:

    Essaye de "ruser" en remplaçant le tracé des lignes par un affichage de sprites.


    C'est exactement ce que j'ai fait  >:) , et c'est pas plus mal comme ça finalement !! L'opacité des ficelles s'estompe en allant vers le ciel, on ne les voit plus au niveau du cerf-volant et c'est même plus réaliste qu'avec des CGPath ^^

    (Je leur fait suivre la direction avec atan2.)

    Et je vais peut-être même me payer le luxe de faire un sprite animé sur 3 ou 4 frames pour faire passer un petit reflet de lumière sur la corde de temps en temps. hé hé  :brule:

    Alors, les persos que tu as posté, ils sont de quel jeu, déjà  ?
  • DrakenDraken Membre
    17:09 modifié #57
    Les planches de sprites 2D que j'ai montré ne proviennent pas d'un jeu, mais d'un outil PC de création de RPG, RPG MAKER VX, un logiciel japonais non commercialisé en france.

    Tu as probablement dus voir des copies d'écrans d'un jeu créé avec cet utilitaire.

  • vico92vico92 Membre
    juillet 2009 modifié #58
    dans 1246738409:

    Les planches de sprites 2D que j'ai montré ne proviennent pas d'un jeu, mais d'un outil PC de création de RPG, RPG MAKER VX, un logiciel japonais non commercialisé en france.

    Tu as probablement dus voir des copies d'écrans d'un jeu créé avec cet utilitaire.


    Je parlais de la planche actors1.png avec les gros plans, ces persos sont tres connus, c clair que j'ai dû jouer à  un jeu avec eux quand j'étais plus jeune.

    EDIT: oui, ou alors c'est que ce soft m'est passé dans les mains, t'as ptetre raison
  • Philippe49Philippe49 Membre
    17:09 modifié #59
    dans 1246715946:

    Trop compliqué pour lui de dessiner une ligne 30 fois par sec., je suis mdr


    Non, ce n'est pas les ressources graphiques de l'iphone qui sont en cause ici. Tu as dû encore nous monter un méli-mélo à  la Vico. La preuve en est que le flush du sprite, beaucoup plus gourmand en ressources, passe ... donc des ressources il y en a encore ...

    Enfin bravo, cela devrait être bien ce que tu prépares !
  • DrakenDraken Membre
    juillet 2009 modifié #60
    Toutes les planches que j'ai montré dans ce topic proviennent du logiciel RPG MAKER VX, y compris les personnages. C'est le style graphique japonais "Chibi" (petit personnage, grosse tête) qui doit t'induire en erreur. Il n'est pratiquement jamais utilisé en Occident. Tu as peut être vu un ancien jeu 2D utilisant le même style.

    EDIT: Il y a des centaines de jeux japonais peu connus en Europe avec des styles graphiques très proches, surtout sur les consoles.

  • Philippe49Philippe49 Membre
    17:09 modifié #61
    dans 1246676198:

    Et laisser le /320 au lieu du * 0.003125 permet de garder un code lisible plutôt que d'y introduire des magic numbers (qui sont à  proscrire)...

    Je plussoie, un bon code ne devrait contenir aucune valeur numérique.
    Ici, pour la lisibilité, j'écrirais

    <br />#define INVERSE_SCREEN_WIDTH 0.003125<br />&nbsp; &nbsp; ...<br />&nbsp; &nbsp; ratioAy = secretView.center.y* INVERSE_SCREEN_WIDTH;<br />
    
Connectez-vous ou Inscrivez-vous pour répondre.