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

SDL Discussion :

Faire tourner une surface autour d'une autre surface


Sujet :

SDL

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Points : 3
    Points
    3
    Par défaut Faire tourner une surface autour d'une autre surface
    Bonjour,

    Je cherche un moyen de faire tourner une surface autour d'un point (d'une surface en forme de boule en réalité) mais je n'y parviens pas.

    Je souhaite que ma surface effectue dans le même temps une rotation.
    J'ai donc pensé à utiliser gfx.

    Mais mes calculs semblent erronés.

    J'ai utilisé les maths et la trigonométrie mais cela fonctionne mal, la surface se comporte très mal au déplacement.

    Voici un aperçu géométrique de mes surfaces :

    http://www.developpez.net/forums/att...1&d=1243636823

    avec ABCD la surface a faire tourner autour de la boule noire sur le dessin en preservant une distance de x pixels autour d'elle, positionObjet les coordonnées de la surface ABCD, positionBoule celles de la boule noire

    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
    20
    void deplacement(SDL_Rect* positionBoule, SDL_Rect* positionObjet, double *AE, double *EF)
    {
        double AB = (double)positionObjet->h; // hauteur de la surface
        double AC = (double)positionObjet->w; // largeur de la surface
     
    	// Utilisation du theoreme de Pythagore
        double AD = sqrt(pow(hauteur, 2) + (pow(AC, 2))); // longueur du côté AD
     
        double cosinus1 = (AB / AD); // cosinus du sommet BÂD
        float angle1 = 180 * (acos(cosinus1)) / M_PI; // angle1 du sommet BÂD
        float angle2 = 90 - angle1; // angle du sommet DÂC
        double AF = AD + 5 + ((double)positionBoule->w / 2); // longueur du côté AF
        double cosinus2 = cos(angle2); // cosinus du sommet DÂC
     
        *AE = (double)cosinus2 * AF; // longueur du côté AE
        *EF = sqrt(pow(AF, 2) - (pow(*AE, 2))); // longueur du coté EF - theoreme de Pythagore
     
        positionObjet->x = positionBoule->x + (positionBoule->w / 2) - (int)*AE; // coordonnée en abscisse du point A
        positionObjet->y = positionBoule->y + (positionBoule->w / 2) - (int)*EF; // coordonnée en ordonnées du point A
    }
    à l'appui de la touche UP du clavier, la surface est modifiée avec l'outil rotozoom comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    case SDL_KEYDOWN:
    	switch(event.key.keysym.sym)
    	{
    		case SDLK_UP:
    		     angle -= 1;
                        Objet = rotozoomSurface(Qb, angle, zoom, 1); // modification de la surface (rotation)
                        deplacement(&positionBoule, &positionObjet, &AE, &EF);
    	             break;
    	}
    Y'a-t-il des choses à rectifier ?
    Existe-t-il une méthode efficace pour faire une rotation autour d'une surface (la boule) ?

    Merci.

    Edit : code modifié pour sa cohérence.
    Images attachées Images attachées  

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Salut

    Comme je n'ai pas la librairie gfx sous la main, je voudrais avoir deux-trois renseignement :

    Imaginons une surface de 30x200 pixel.
    On utilise gfx afin d'effectue une rotation (30° disons).
    La surface retourné est-t'elle de dimension 30x200 ?

    Autre chose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    case SDL_KEYDOWN:
    	switch(event.key.keysym.sym)
    	{
    		case SDLK_UP:
    		     angle -= 1;
                        Objet = rotozoomSurface(Qb, angle, zoom, 1); // modification de la surface (rotation)
                        deplacerQueue(&positionBoule, &positionObjet, &AE, &EF);
    	             break;
    	}
    Tu n'appelle pas cette fonction
    Je crois que deplacerQueue = deplacement , non ?

    Sinon, donne nous le code de deplacerQueue stp.

    A +



    Edit : En regardans vite fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     double AD = sqrt(pow(hauteur, 2) + (pow(largeur, 2))); // longueur du côté AD
    hauteur et largeur ne sont pas passer par paramètre et ne sont pas déclarer ...
    Se sont des variables globale ?
    C'est mauvais si c'est le cas ! c'est peut être pour ca que tu deplacement est bizarre.

    sinon, je pensais que hauteur = AB et largeur = AC.
    est ce que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     double AD = sqrt( pow(AB, 2)  + pow(AC, 2) ); // longueur du côté AD
    correspond a ce que tu veux faire ou bien AB est different de hauteur ??

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Points : 3
    Points
    3
    Par défaut
    Alors déjà concernant la taille de la surface après modification, elle est elle aussi modifiée, elle s'adapte en hauteur et largeur. Une surface pivotée à 30° est donc plus haute mais aussi plus large.

    deplacerQueue(&positionBoule, &positionObjet, &AE, &EF);
    -> c'est en fait la fonction deplacement.

    double AD = sqrt(pow(hauteur, 2) + (pow(largeur, 2))); // longueur du côté AD
    -> hauteur est en fait AB et largeur AC, j'ai commis quelques erreurs de "traduction" car j'ai modifié le nom de mes variables pour que vous compreniez mieux le problème et les étapes auxquelles j'ai procédé.

  4. #4
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Ok, je vais ton code plus en profondeur.

    Sinon, est ce que ton sprite se deplace de maniere totalement incoherente ?
    Est ce qu'il fait un cercle ? Si il fait un semblant de cercle, le centre est-il excentrer ? le cercle fait bien un cercle ou plutot un ovale ?

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Points : 3
    Points
    3
    Par défaut
    Le sprite se déplace très mal, il fait comme des bonds en abscisse de plusieurs dizaines de pixels par l'avant et revient en arrière, de manière saccadée. C'est donc totalement incohérent.

    Le tracé de la trajectoire ne s'apparente même pas à un cercle, je ne vois d'ailleurs pas pourquoi celle-ci est aussi saccadée.

    il n'y a que la rotation qui s'effectue correctement (heureusement).

  6. #6
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Bon, j'ai refais un autre code parce que je m'en sortais plus avec le tiens ^^'

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
    #include <stdlib.h>
    #include <SDL/SDL.h>
    #include <SGE/sge.h>
    #include <math.h>
     
    // define (ou constante) permettant de savoir la distance BalleNoir <-> QueueBillard
    #define DISTANCE 50
     
     
    void DeplacementQueueBillard(int angle, SDL_Rect positionBalleNoir, SDL_Surface *QueueBillard);
     
    int main ( int argc, char** argv )
    {
        SDL_Init(SDL_INIT_VIDEO);
     
        SDL_Event event;
        SDL_Surface *ecran = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
     
        SDL_Surface *BalleNoir = SDL_LoadBMP("BalleNoir.bmp");
        SDL_Surface *QueueBillard = SDL_LoadBMP("QueueBillard.bmp");
     
     
        int angle = 0;
        // On n'a pas besoin de connaitre la position de QueueBillard, on l'a deduit avec
        // la position de la BalleNoir, le define DISTANCE et la largeur/hauteur de l'image qui a subi une rotation
        SDL_Rect positionBalleNoir;
            positionBalleNoir.x = ecran->w/2 - BalleNoir->w/2;
            positionBalleNoir.y = ecran->h/2 - BalleNoir->h/2;
     
        SDL_Rect centreBalleNoir;
            centreBalleNoir.x = positionBalleNoir.x + BalleNoir->w/2;
            centreBalleNoir.y = positionBalleNoir.y + BalleNoir->h/2;
     
        int continuer = 1;
        while (continuer)
        {
            SDL_PollEvent(&event);
            switch(event.type)
            {
                case SDL_QUIT :
                    continuer = 0;
                break;
                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_UP:
                            // On MAJ L'angle
                            angle ++;
                            if (angle > 360)
                                angle = 0;
     
                            // On remplit l'ecran de blanc
                            SDL_FillRect(ecran,0 , 0xffffff);
                            // On blit QueueBillard
                            DeplacementQueueBillard(angle, centreBalleNoir, sge_transform_surface(QueueBillard, 0xff0000, angle, 1, 1, 0) );
                        break;
     
                        case SDLK_DOWN:
                            // On MAJ L'angle
                            angle --;
                            if (angle < 0)
                                angle = 360;
     
                            // On remplit l'ecran de blanc
                            SDL_FillRect(ecran,0 , 0xffffff);
                            // On blit QueueBillard
                            DeplacementQueueBillard(angle, centreBalleNoir, sge_transform_surface(QueueBillard, 0xff0000, angle, 1, 1, 0) );
                        break;
     
     
     
                        // Evite d'avoir tout les warning
                        default :
                        break;
                    }
            }
     
     
            SDL_BlitSurface(BalleNoir, NULL, ecran, &positionBalleNoir);
            SDL_Flip(ecran);
        }
     
     
        SDL_Quit();
    }
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
     
    void DeplacementQueueBillard(int angle, SDL_Rect centreBalleNoir, SDL_Surface *QueueBillard)
    {
        // On va calculer la distance BalleNoir <-> QueueBillard en tenant compte de l'angle ( ne pas oublier la conversion)
        SDL_Rect positionQueueBilard;
        positionQueueBilard.x = centreBalleNoir.x + DISTANCE * cos(angle*M_PI/180);
        positionQueueBilard.y = centreBalleNoir.y + DISTANCE * sin(angle*M_PI/180);
     
        /*Il y a maintenant quatre cas :
     
        X = QueueBillard    + = BalleNoir
     
        1)      X|
                -+-
                 |
     
        2)       |X
                -+-
                 |
     
        3)       |
                -+-
                 |X
     
        4)       |
                -+-
                X|
                
                
        /!\  Attention  /!\
        
        cercle trigo du PC :         270
                                      |
                                 180 -+- 0
                                      |
                                     90
     
        */
     
        if ((90 <angle) && (angle <= 180))
            positionQueueBilard.x -= QueueBillard->w;
        else
            if ((180 <angle) && (angle <= 270))
            {
                positionQueueBilard.x -= QueueBillard->w;
                positionQueueBilard.y -= QueueBillard->h;
            }
            else
                if ((270 <angle) && (angle <= 360))
                    positionQueueBilard.y -= QueueBillard->h;
     
     
        SDL_BlitSurface(QueueBillard, NULL, SDL_GetVideoSurface(), &positionQueueBilard);
     
    }

    Alors, j'explique :

    Je mets un define pour fixer la distance BalleNoir <-> QueueBillard.
    Cette distance est en pixels.

    Lorsque tu appuis sur haut (ou bas ), tu MAJ angle (normal).
    Ensuite tu appel la fonction DeplacementQueueBillard qui se chargera de blitter l'image QueueBillard.

    Dans la fonction DeplacementQueueBillard, je calcul dans un premier temps, selon angle et centreBalleNoir ou sera blitter QueueBillard.
    Or, ce point trouver n'est pas forcement les coordonne du coin superieur gauche.
    C'est pour ca que dans second temps, selon l'angle, je retire la hauteur et/ou la largeur de l'image sauf entre 0 et 90°.

    Voila, voila.
    Si je suis trop confus dans mes explication, dis le moi.

    Après, c'est a toi d'adapter le code selon tes besoins.

    PS : mon image QueueBillard est une image de 2 pixels de hauteur et de 100 pixels de largeur.

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Points : 3
    Points
    3
    Par défaut
    Je te remercie de m'aider.

    Je ne dispose pas de la bibliotheque SGE, peux tu m'expliquer brièvement ce que fait l'appel de cette fonction :

    sge_transform_surface(QueueBillard, 0xff0000, angle, 1, 1, 0)

    J'ai essayé de faire avec la blibliotheque rotozoom mais il semblerait que ce soit different, en tout cas ma queue de billard se comporte étrangement, elle fait des tours dans le bon sens mais ne tourne pas autour de la boule

  8. #8
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Merde, je suis trop ***.

    Désolé, je croyais l'avoir expliquer ....

    sge_transform_surface(QueueBillard, 0xff0000, angle, 1, 1, 0)

    Cette fonction retourne un SDL_Surface

    le 1er parametre est le SDL_Surface a envoyer
    le deuxieme (0xff0000 ) est la couleur d'arriere plan apres passage.
    Le troisieme, c'est l'angle ^^ (passer en mode degres )
    le 4 et 5 concerne le zoom, donc j'ai mis 1 pour conserver l'image
    le dernier concerne des flag, je l'ai mis a 0


    Voila, tu sais tout ce cette fonction ^^

    Il y a encore un probleme ?
    Quand j'appuis sur le haut, la canne tourne dans le sens des aiguille d'une montre (pas logique, je l'avoue), mais il suffit de changer angle++ par angle--

  9. #9
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Ahhhh Je crois comprendre le comportement de ta canne ^^
    En fait, pour 0°, la queue de billard se situe juste a droite.
    Par consequent, il faut que l'image que tu charge represente une queue de billard horizontale.
    Je suppose que la tienne est en verticale ^^
    non ?


    Si y a d'autres prob, hesite pas

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Points : 3
    Points
    3
    Par défaut
    Après deux trois bricoles, ça fonctionne impeccable.

    Je ne sais pas si c'est parce que j'utilise rotozoom, mais j'ai du changer prendre un angle différent pour faire pivoter la canne que j'ai nommé angle2 et que je décrémente quand j'incrémente angle et que j'incrémente quand je décrémente angle.

    Ensuite, j'ai mis un angle de base de 180° pour ma canne sans quoi elle pointait dans le mauvais sens en direction de la boule.
    La raison, ma canne est sans doute orientée dans l'autre sens dans mon sprite par rapport à toi.

    Merci

    Edit : par contre quand je déplace la canne, juste avant de franchir les 0, 90, 180, 270 et 360° elle avance de quelques pixels et donc le déplacement n'est pas uniforme. Comment expliquerais-tu cela ?

  11. #11
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Envoie moi ton code s'il te plait.

    quant tu dis qu'elle avance de quelque pixel ... c'est vers le centre ?
    Regarde dans mes conditions s'il y a toujours le "<=", cela vient peut etre de ca.


    Ensuite, j'ai mis un angle de base de 180° pour ma canne sans quoi elle pointait dans le mauvais sens en direction de la boule.
    La raison, ma canne est sans doute orientée dans l'autre sens dans mon sprite par rapport à toi.

    Mais pourquoi ?
    Il suffisait de changer le sprite ! C'est toujours mieux que de mettre des bidouilles dans le code qui le rende moins clair ...

  12. #12
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Points : 3
    Points
    3
    Par défaut
    Je t'ai envoyé le code en MP.

Discussions similaires

  1. Réponses: 7
    Dernier message: 21/09/2009, 10h10
  2. Faire tourner un MovieClip autour d'un autre
    Par direct dans le forum Flash
    Réponses: 4
    Dernier message: 08/12/2008, 14h42
  3. Faire 2 traits infini autour d'une image.
    Par Psykolyqc dans le forum Mise en page CSS
    Réponses: 17
    Dernier message: 01/01/2008, 17h02
  4. Réponses: 2
    Dernier message: 17/10/2006, 17h00
  5. copie d'une table Y d'une base A vers une table X d'une base
    Par moneyboss dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 30/08/2005, 21h24

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