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

SFML Discussion :

avancer en fonction de la rotation


Sujet :

SFML

  1. #1
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Août 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Août 2022
    Messages : 5
    Points : 2
    Points
    2
    Par défaut avancer en fonction de la rotation
    Bonjour, je cherche à faire avancer en continue un sprite en fonction de sa rotation. Je tiens à préciser que sa rotation change tout le temps et que la fonction s'occupant de ça marche trés bien.

    Voici la ligne que j'ai essayé (qui est dans la boucle d'sfml)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    move(cos(this->getRotation()), sin(this->getRotation()));
    la plupart du temps le sprite avance bien mais dés que sa rotation est environ égal à 0 (donc le sprite est orienté vers le haut de l'écran), il s'arrête d'avancer et se met à reculer. j'ajoute aussi que quand le sprite avance en meme temps qu'il tourne, il se met à trembler (je pense que c'est parce qu'il recule et avance en meme temps)

    merci de vos réponses et de votre aide ^^

  2. #2
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 393
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 393
    Points : 20 496
    Points
    20 496
    Par défaut
    peut-être qu'il suffit de tester l'angle ==0.
    Si c'est le cas alors angle=360

  3. #3
    Membre actif
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2018
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juillet 2018
    Messages : 99
    Points : 223
    Points
    223
    Par défaut
    Il se trouve que le getRotation de SFML retourne des degrés alors que les cos/sin classique prennent des radians. Il te faut donc le facteur PI/180 entre les deux.
    Je ne pense pas que ça explique tous tes "symptômes", mais tu peux déjà voir ce que ça arrange. S'il y a d'autres problèmes, il faudra peut-être chercher sur d'autres lignes.

  4. #4
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 461
    Points : 4 637
    Points
    4 637
    Par défaut Plus long & plus court
    Bonjour,

    J'éviterais de faire deux appels pour calculer le cos et le sin car l'angle peut avoir changé entre temps.

    Avec des variables intermédiaires, on peut éviter nombre de recalculs.

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    double RotNew = 0.017453292*getRotation(); // en radians
    if(RotNew != RotLast) { // ou mettre un seuil abs(RotNew -RotLast) > 0.01 par exemple 
       CosLast = cos(Rot);
       SinLast = sin(Rot);
       RotLast = RotNew;
       }
    move(CosLast, SinLast);
    Je présume que ce move accepte des flottants et gère les partie fractionnaires résiduelles ?

    Salutations

  5. #5
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 053
    Points
    33 053
    Billets dans le blog
    4
    Par défaut
    Il recule ? Donc cos retourne < 0 ? Alors que tu vas vers le haut ?
    Est-ce que en haut a une rotation de 90 ou de 0 et tu oublies d'ajuster la valeur sur ton échelle ?
    Ou bien la rotation oscille un peu faisant que tu vas pas à 90 mais [89-91] et donc cos oscille aussi.
    Vérifie que ta rotation soit correcte. cos et sin prennent des radians, est-ce que ta rotation est en radian ou en degrès ?
    https://cplusplus.com/reference/cmath/sin/
    Tu pourrais / devrais aussi stocker le vecteur de direction directement plutôt que de recalculer cos & sin chaque fois. Ces fonctions sont lentes.

  6. #6
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Août 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Août 2022
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Tout d'abord bonjour et merci pour vos réponses


    en faite quand je dis que des que sa rotation est environ égal à 0 j'inclue de 359 virgule quelque chose à 0 virgule quelque chose, donc changer l'angle en 360° ne changera rien (j'ai quand même essayé et effectivement ça n'affecte rien du tout).

    ensuite, effectivement ça pouvait marcher (et ce serait logique) de convertir les angles en radian mais malheureusement ça ne fait qu'empirer les choses car le sprite se met à "trembler" (c'est-à-dire qu'il avance et recule en même temps) et c'est la seul ligne qui permet de faire avancer le sprite donc impossible de chercher sur d'autres lignes le problème
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    move(cos(this->getRotation() * 180 / 3.1415927f), sin(this->getRotation() * 180 / 3.1415927f));
    (je met quand même le code ici au cas où)

    oui move accepte les flottants et les parties fractionnaires résiduelles. J'ai essayé ton code je suppose que Rot est égal à RotNew et le résultat est que le sprite avance en cercle autour du point vers lequel il doit normalement avancer (j'espère que j'ai bien expliqué)

    en haut, j'ai une rotation environ égal à 0 et il recule quand il est tourné vers cette orientation (je sais que que l'orientation 0 en trigo est sur la droite, j'aurais du être plus précis). oui il ocsille aussi, c'est pour ça que je dis environ égal (j'aurais encore du être plus précis, décidemment). Je ne savais pas que cos et sin était lent, merci de m'avoir prévenu


    encore merci de m'avoir répondu aussi vite et désolé pour le manque de précisions
    cordialement

  7. #7
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 393
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 393
    Points : 20 496
    Points
    20 496
    Par défaut
    Est-ce que le problème est résolu alors ?

  8. #8
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Août 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Août 2022
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    non malheureusement

  9. #9
    Membre actif
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2018
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juillet 2018
    Messages : 99
    Points : 223
    Points
    223
    Par défaut
    Citation Envoyé par jaimeBcpLesPizzas Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    move(cos(this->getRotation() * 180 / 3.1415927f), sin(this->getRotation() * 180 / 3.14159276f));
    (je met quand même le code ici au cas où)
    Ben, 1 chance sur 2 (Enfin, pas tout à fait, j'avais précisé PI/180 et pas 180/PI).
    Pour ne pas confondre le sens, il faut te dire que quand getRotation vaut 360°, tu dois envoyer 2pi au cos/sin.

  10. #10
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Août 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Août 2022
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    ah oui j'avais pas remarqué,

    j'ai essayé et le resutat est le même que le code de Guesset, c'est à dire qu'il avance en cercle autour du point vers lequel il doit avancer en ligne droite (en d'autres mots il avance sur le périmètre d'un cercle centrer sur le point qu'il doit atteindre)

  11. #11
    Membre actif
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2018
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juillet 2018
    Messages : 99
    Points : 223
    Points
    223
    Par défaut
    il avance en cercle autour du point vers lequel il doit avancer en ligne droite (en d'autres mots il avance sur le périmètre d'un cercle centrer sur le point qu'il doit atteindre)
    J'imagine que tu fais donc un "setRotation" en fonction de la position courante et la position cible.
    Théoriquement, pour ça, il faut faire quelque chose comme (vive la trigo):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    setRotation(180/pi * atan2(cibleY - posY, cibleX - poX))
    Il faudrait que tu nous partages la ou les lignes qui font ça pour le constater, mais ce comportement veut certainement dire que tu as échangé les Y et les X et peut-être des histoires de signe.
    Cette formule doit correspondre à "l'inverse" de ta formule du move. Elle donne l'angle à partir de la direction, et lors du move tu donnes la direction à partir de l'angle.

    Sans parler de sprite, mais juste de géométrie, les "directions" se réprésentent avec des vecteurs (sf::Vector2f pour SFML), et tu passes donc entre les directions et les angles avec quelque chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    const float degToRad = pi / 180.0f;
    sf::Vector2f angleToDirection(double angle) {
        return { cos(degToRad * angle), sin(degToRad * angle) };
    }
    double directionToAngle(const sf::Vector2f& direction) {
        return atan2(direction.y, direction.x) / degToRad;
    }
    Tu remarqueras d'ailleurs que move peut directement prendre un sf::Vector2f en paramètre, ce qui est quand même plus naturel.

  12. #12
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 461
    Points : 4 637
    Points
    4 637
    Par défaut Angle ou vecteur ?
    Bonjour MoiAussi,

    Citation Envoyé par jaimeBcpLesPizzas Voir le message
    ...J'ai essayé ton code je suppose que Rot est égal à RotNew et le résultat est que le sprite avance en cercle autour du point vers lequel il doit normalement avancer (j'espère que j'ai bien
    expliqué)...
    Donc l'angle n'est pas un angle absolu mais un angle relatif à la direction actuelle du sprite. Je présume que le move(cs, sn) calcule quelque chose comme : vitesse = (v*(cos(a)*cs + sin(a)*sn, v*(sin(a)*cs + cos(a)*sn) où a est l'angle absolu de déplacement courant. En l'absence de changement de direction, cs = 1.0 et sn = 0.0, la vitesse = (v*cos(a), v*sin(a)) reste inchangée. On voit que la moindre erreur (comme le fait que l'angle est lu 2 fois) amplifiée par le module de la vitesse peut induire des écarts plus ou moins importants. Avec un peu de chance la somme en sera nulle et le sprite ira bien là où il doit aller mais avec quelques verres dans le nez.

    Si le move est une fonction sur laquelle tu as la main, j'aurais tendance à travailler directement avec l'angle (move(da) ou peut être mieux turn(da) ) et j'appliquerais un seuil à la variation angulaire pour ramener à 0.0 les valeurs qui en sont très proches (0.0+e, 2*PI-e). L'intérêt de travailler directement avec l'angle est de limiter les calculs et les accumulation d'approximations.
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if(abs(da) > 0.006 ||  abs(da-PIx2) > 0.006) { // Ici seuil  de l'ordre de 0.4°
       a += da;   
       vx = v*cos(a); // utiliser sincos si disponible
       vy = v*sin(a); 
       // ... rotation du sprite d'origine de a
       }
    ...
    Ce code n'est qu'une illustration du principe et ne prétend nullement être applicable tel quel. Il y a par exemple le présupposé que l'angle reste entre -360° et +360°. Par ailleurs; il est vraisemblable que l'angle ne peut varier brutalement comme passer directement à 180° pour un demi tour instantané.

    Salut.

  13. #13
    Candidat au Club
    Homme Profil pro
    Collégien
    Inscrit en
    Août 2022
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Août 2022
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    c'est bon, sujet résolu !

    j'ai directement passé la fonction me permettant de calculer l'angle (donc atan2) en argument à cosinus et à sinus à partir d'une variable au lieu de passer par getRotation et de faire plusieurs conversions inutiles (et peut être faire des erreurs comme inverser X et Y ou autres)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //recupère l'abcisse de la position de la souris sur la fenêtre moins l'abscisse actuelle du sprite
    float x = m_fenetre->mapPixelToCoords(sf::Mouse::getPosition(*m_fenetre)).x - getPosition().x;
    //recupère l'ordonnée de la position de la souris sur la fenêtre moins l'ordonnée actuelle du sprite
    float y = m_fenetre->mapPixelToCoords(sf::Mouse::getPosition(*m_fenetre)).y - getPosition().y;
     
    float rotationActuelle{ getRotation() };
    double angle{};
     
    if (rotationActuelle != RotLast)
    {
            angle = atan2f(y, x);
            RotLast = rotationActuelle;
    	CosLast = cos(angle);
    	SinLast = sin(angle);
    }
     
    setRotation(angle * 180 / PI);
     
    move(CosLast, SinLast);
    merci à vous tous
    cordialement

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

Discussions similaires

  1. Fonction contrôle de rotation
    Par Dave72 dans le forum Automation
    Réponses: 2
    Dernier message: 27/07/2014, 08h36
  2. [Article] Usage avancé des fonctions JavaScript
    Par Bovino dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 21/12/2011, 00h06
  3. Gauge qui avance en fonction d'un Timer
    Par Alyx² dans le forum Delphi
    Réponses: 10
    Dernier message: 02/03/2007, 14h06

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