IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

If qui passe pas ! Incompréhensible !


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2012
    Messages : 8
    Par défaut If qui passe pas ! Incompréhensible !
    Bonjour.

    J'ai un bout de code sur lequel je me prends la tête depuis 2 jours déjà!

    J'utilise SDL, mais c'est juste anecdotique ici.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int dt = timer->get_ticks();
     
    if (input->MouseButtonPressed[0] || input->AnyKeyIsPressed){
        ScreenTimer = 0;
    }
    if (ScreenTimer > 0){
        ScreenTimer -= 1 * dt;
    }
    else{
        SDL_Quit();//On ferme juste historie de mettre un bien voyant pour qu'on voit que ça marche
    }
    ScreenTimer est défini à 11000 (c-a-d 11 secondes).



    La première ligne représente dt (qui varie entre 9 et 12).
    La seconde ligne représente ScreenTimer qui commence à 11000 puis qui descend encore et encore jusqu'à arrivé à 0... Puis part en négatif... Et rien ne se passe !



    Le pire c'est que si j'enleve le dt et que je laisse juste ScreenTimer -= 1; quand ScreenTimer arrivera à 0 le if fonctionnera bel et bien. Après quelques test il faut que ScreenTimer arrive pile poil sur 0 pour faire trigger le if...

    Quand je presse une touche ou que je fais click gauche (premier if) ScreenTimer est bien défini sur 0 et le programme lance bien le SDL_Quit();

    Totalement incompréhensible...

    La classe du timer est bateau...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void Timer::start(){
        startTicks = SDL_GetTicks();
    }
    
    void Timer::tick(){//appelé à chaque itération de la main loop
        startTicks = SDL_GetTicks();
    }
    
    int Timer::get_ticks(){
        return SDL_GetTicks() - startTicks;
    }
    Je commence à m'arracher les cheveux...

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Bonsoir,

    quel est le type de ScreenTimer ? Si c'est non signé, il ne sera jamais négatif.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2012
    Messages : 8
    Par défaut
    C'est un int mais même en le passant en unsigned il part quand même en négatif.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned int ScreenTimer;

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Août 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2012
    Messages : 8
    Par défaut
    Bon j'ai fait ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (ScreenTimer +100 > 100){
         ScreenTimer -= 1 * dt;
    }
    Et ça marche.

    C'est à n'y rien comprendre... Le 0 est buggé, c'est la fin du monde !

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par InStep Voir le message
    Bon j'ai fait ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (ScreenTimer +100 > 100){
         ScreenTimer -= 1 * dt;
    }
    Et ça marche.

    C'est à n'y rien comprendre... Le 0 est buggé, c'est la fin du monde !
    Non, le 0 n'est pas buggé, mais il faut comprendre comment fonctionne un ordinateur.

    Sache d'abord que tout, dans un ordinateur n'est jamais, pour utiliser une comparaison à la fois simple et relativement correcte, qu'une succession d'interrupteurs.

    Au lieu de parler d'interrupteurs, on parle de bits

    Ces interrupteurs ne peuvent représenter que deux états: soit ils laissent passer le courent, et on leur donne alors la valeur 1, soit ils ne le laissent pas passer, et on leur donne alors la valeur 0.

    Quel que soit le langage utilisé, tout ce que tu écris, sauvegarde sous la forme d'un fichier ou même transmets d'un ordinateur à l'autre ne se réduira au final qu'à une succession de 1 et de 0 qui représenteront chaque fois l'état d'un interrupteur.

    A chaque type primitif (char, short, int, long, long long, float et double) correspond un nombre d'interrupteur.

    Sur les architecture classiques, un char correspond à une succession de 8 interrupteurs, c'est la raison pour laquelle on parle en français d'octet (alors qu'il faudrait en réalité parler de multibits ou mieux, utiliser le terme anglais "byte" pour ne pas se cantonner aux seules architectures basées sur des bytes de 8 bits )

    Ainsi, le type int est, classiquement, composé de 4 bytes, soit 32 bits.

    Seulement, à défaut de préciser le contraire, quel que soit le type entier représenté (char, short, int, long, long long), il y a un des bits (le bit "de poids le plus fort" en théorie) qui a une signification particulière.

    C'est ce que l'on appelle "le bit de signe": s'il vaut 1, on a une valeur négative, s'il vaut 0, on a une valeur positive.

    si l'on prend l'exemple (car il est plus simple ) d'un char codé sur 8 bits, on dispose donc 7 bits pour représenter les valeurs, et du bit de signe qui permet de représenter le fait qu'il s'agisse d'une valeur ppositive ou négative.

    Toutes les valeurs que l'on pourrait représenter en hexadécimal entre 0x00 et 0x7F (comprises entre 0 et 127 en décimale) seront donc positives alors que toutes les valeur que l'on représenterait en décimale entre 0x80 et 0xFF seront considérées comme négatives.

    Au niveau d'un int, nous avons donc des valeurs positives pour tout ce qui est compris entre 0x00000000 et 0x7FFFFFFF et des valeurs négatives pour toute valeur comprise entre 0x80000000 et 0xFFFFFFFF.

    (Je te passe la manière de calculer les valeurs négatives car cela n'apporterait pas grand chose à l'explication, mais n'hésites pas à demander si ça t'intéresse )

    Seulement, voilà: Tous les types entiers existent dans la forme signée (que je viens d'expliquer) et la forme non signée.

    Dans leur forme non signée, le bit de signe sert également pour représenter les valeurs, ce qui fait que toutes les valeurs comprises (pour un char) entre 0x00 et 0xFF en hexadécimal (entre 0 et 255) sont d'office positive, et il n'y a, purement et simplement, aucun moyen d'obtenir une valeur négative.

    Avec un unsigned int, tu n'as donc absolument aucune chance pour qu'une condition basée sur "< 0" ne puisse jamais être vérifiée car 0 - 1 donnera la valeur hexadécimale 0xFFFFFFFF et que cette valeur est... positive, et que toute valeur positive est, d'office, plus grande que 0 (Monsieur Lapalisse n'aurait pas dit autrement )

    Il est d'ailleurs plus que probable que, si tu configure correctement ton compilateur, il se fende d'un avertissement t'indiquant que cette condition sera toujours fausse

    Si ton timer est de type unsigned int , le seul moyen de t'assurer que tu t'arrête effectivement une fois que tu "dépasse" 0 en décrémentant ta valeur est d'effectuer un test proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* codé pour garder la même logique */
    if(ScreenTimer < ScreenTimer -1 *dt)
    {
        ScreenTimer -= 1*dt;
    }
    else
    {
        SDL_Quit();
    }
    L'idéal étant sans doute d'adapter un tout petit peu la logique sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    unsigned int temp = ScreenTimer -1*dt
    if(temp> screenTimer)
    {
        SDL_QUIT();
    }
    sreenTimer = temp; // si on passe ici, c'est qu'on n'a pas atteint 0
    Si d'aventure l'affichage te donne une valeur négative, ce n'est pas à cause du type timer (qui, il faut en convenir, n'a aucune raison de pouvoir représenter une valeur négative : on ne saura jamais attendre "-3 secondes" ), ni parce que "le 0 est buggé", mais, très certainement parce que la fonction qui doit afficher la valeur du timer pose problème en prenant un paramètre de type int alors qu'il faudrait qu'elle prenne un paramètre de type unsigned intMais, encore une fois, ton compilateur devrait te l'indiquer sous la forme d'un avertissement si tu utilisais les bonnes options de compilation
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par InStep Voir le message
    C'est un int mais même en le passant en unsigned il part quand même en négatif.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned int ScreenTimer;
    Il "part en négatif" car il doit être casté quelque part en int pour l'affichage.

    Sinon tout indique ici un problème de comparaison unsigned int <-> int :
    - le fait que ScreenTimer ne soit jamais négatif
    - le hack avec le +100 et comparaison à 100, (qui ne marche que parce que 100 > timer->get_ticks() )

    Si c'est bien un int, je serais vraiment curieux de savoir ce qui se passe exactement et pourquoi ça ne marche pas.

  7. #7
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Cela n'est sans doute pas l'erreur mais pourquoi faire x -= 1 * y; plutôt que x -= y; le résultat sera le même non ?

    Si tu veux faire un compte à rebours de 11 secondes pourquoi réinitialiser ton timer ( tick() ) à chaque itération plutôt que de conserver ton start() auquel tu soustrairas ton getStick() ?
    Ton dt sera speut-être souvent égale à zéro !

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Août 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2012
    Messages : 8
    Par défaut
    Chouette ça marche, et en plus j'ai appris des trucs. Merci Koala!

    Citation Envoyé par PilloBuenaGente Voir le message
    Cela n'est sans doute pas l'erreur mais pourquoi faire x -= 1 * y; plutôt que x -= y; le résultat sera le même non ?
    C'est vrai. En fait j'ai pris l'habitude de mettre des multiplicateur sur les variables qui s'implémentent ou qui se soustraient "en boucle", ça me permet d'augmenter rapidement la "vitesse" d’exécution. J'allais pas attendre à chaque fois 11 secondes! Donc je laisse le *1 par ... auto-convention.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] requete SQL qui passe pas avec note pad++ but phpmyAdmin
    Par southCfou dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 26/11/2008, 11h20
  2. Key Listener qui passe pas
    Par FCDB dans le forum Interfaces Graphiques en Java
    Réponses: 2
    Dernier message: 09/04/2007, 21h31
  3. domxml caractère qui passe pas
    Par gabychon dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 19/05/2006, 14h08
  4. [MySQL] un echo qui passe pas ^^
    Par Le Mage Noir dans le forum PHP & Base de données
    Réponses: 15
    Dernier message: 09/02/2006, 15h05
  5. [Oracle 9.i] Requête qui passe pas
    Par ftrifiro dans le forum Langage SQL
    Réponses: 7
    Dernier message: 20/12/2005, 17h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo