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 :

[SDL] Limiter le déplacement de mon presonnage (jeux type point and click)


Sujet :

SDL

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

    Informations forums :
    Inscription : Juillet 2009
    Messages : 11
    Points : 4
    Points
    4
    Par défaut [SDL] Limiter le déplacement de mon presonnage (jeux type point and click)
    Salut à tous les couche tard

    j'ai un petit problème avec la fonction qui limite le déplacement de mon personnage à un polygone .
    C'est un point and click , la fonction vérifie ou le joueur clique et si il clique a l'intérieur de la limite de déplacement (un polygone) , le personnage ce déplace.

    J'utilise cette méthode :
    Soit le segment [AB], et le segment [CD].
    Je note I le vecteur AB, et J le vecteur CD

    Soit k le parametre du point d'intersection du segment CD sur la droite AB. on sera sur le segment si 0<k<1
    Soit m le parametre du point d'intersection du segment AB sur la droite CD, on sera sur le segment si 0<m<1

    Soit P le point d'intersction
    P = A + k*I; // equation (1)
    P = C + m*J;

    D'ou :
    A + k*I = C + m*J

    On décompose les points et vecteurs, on a :
    Ax + k*Ix = Cx + m*Jx
    Ay + k*Iy = Cy + m*Jy

    2 équations, 2 inconnues, en résolvant, on trouve :

    m = -(-Ix*Ay+Ix*Cy+Iy*Ax-Iy*Cx)/(Ix*Jy-Iy*Jx)
    k = -(Ax*Jy-Cx*Jy-Jx*Ay+Jx*Cy)/(Ix*Jy-Iy*Jx)

    (Notez que les dénominateurs sont les meme)
    Attention, si Ix*Jy-Iy*Jx = 0 , alors les droites sont paralleles, pas d'intersection.
    Sinon, on trouve m et k

    On vérifie que 0<m<1 et 0<k<1 --> sinon, cela veut dire que les droites s'intersectent, mais pas au niveau du segment.
    Ensuite, pour retrouver P, on réinjecte m ou k dans une des 2 équations (1)
    Donc en fait :
    Z = (I.x * J.y - I.y * J.x)
    m = -(-I.x * S1A.y + I.x * S2A.y + I.y * S1A.x - I.y * S2A.x)/ Z
    k = -( S1A.x * J.y - S2A.x * J.y - J.x * S1A.y + J.x * S2A.y)/ Z

    Si m et k sont plus grands que zero et plus petits que 1 alors les segments s'intersecte .

    La j'ai juste commencer la fonction et normalement , il devrait y avoir toujours au moins une section donc, cela devrais tout le temps marcher quand je clique dans le polygone , or ça ne marche jamais ...?

    voici en gros mon main.c (il n'est pas comme ça en vrai)

    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
    typedef struct coord coord ;
    struct coord
    {
        long x;
        long y;
    };
     
    typedef struct poly poly ;
    struct poly
    {
        coord point[70];
    };   
     
    int main ()
    {
     
        long joueurDansZone = 0;
        coord clic;
        poly polygone;
        polygone.point[0].x = 515 ;
        polygone.point[0].y = 235 ;
        polygone.point[1].x = 30  ;
        polygone.point[1].y = 559 ;
        polygone.point[2].x = 800 ;
        polygone.point[2].y = 559 ;
        polygone.point[3].x = 800 ;
        polygone.point[3].y = 446 ;
        polygone.point[4].x = 550 ;
        polygone.point[4].y = 235 ;
     
    // BLA BLA BLA , LES EVENEMENTS ( dans une boucle ect...) :
     
            if (evenement.button.button == SDL_BUTTON_LEFT)//Clik gauche (Action)
                {
                    if ( curseur == Curseur_normal ) // Curseur par défaut (déplacement)
                    {
                         clic.y = evenement.button.y ; // Les coordonnées de clic sont celle de l'endroit ou on a cliquer 
                         clic.x = evenement.button.x ;
                         joueurDansZone =  clicPoly ( 5 , polygone , clic  );
     
                         if (joueurDansZone == 1)
                         {
                             positionPerso.y = evenement.button.y - 220 ; // On enlève la taille du sprite
                             positionPerso.x = evenement.button.x - 34  ; // Le bas est centrer au milieu (le perso fait 68 px)
                         }
     
     
                     }
               }
    }
    voici le fichier contenant les fonctions :
    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
    int clicPoly ( long nbppoly , poly polygone , coord clic  )
    {
      int i , sect = 0 ;
      coord infini;
      infini.x = 3000 ;
      infini.y = 4000 ;
     
      for ( i=0 ; i != nbppoly ; i++)
      {
          sect = sectSegment ( polygone.point[i] , polygone.point[i+1] , clic , infini) ;
          if ( sect == 1 )
            return 1;
      }
      return 0;
    }
     
    int sectSegment (coord A , coord B , coord clic , coord infini)
    {
        coord vects1 , vects2 ;
        long m , m1 , m2 , k , k1 , k2 , z , continuer = 1 ;
     
        while (continuer)
        {
            z = m = k = 0 ;
     
            vects1.x = B.x - A.x ;
            vects1.y = B.y - A.y ;
     
            vects2.x = infini.x - clic.x ;
            vects2.y = infini.y - clic.y ;
     
            z = vects1.x * vects2.y - vects1.y * vects2.x ;
     
            if (z == 0)
            {
                infini.x ++;
                infini.y ++;
            }
     
            else if ( z != 0)
            {
                m1 = ( -vects1.x * A.y ) + ( vects1.x * clic.y ) ;
                m2 = ( vects1.y * A.x ) - ( vects1.y * clic.x ) ;
                m = (- m1 + m2 )  / z ;
     
                k1 = ( A.x * vects2.y ) - ( clic.x * vects2.y );
                k2 = ( vects2.x * A.y ) + ( vects2.x * clic.y );
                k = (- k1 - k2 ) / z ;
     
                if (m > 0 && m < 1 && k > 0 && k < 1 )
                    return 1;
                else
                    return 0;
            }
     
            else
            {
                fprintf(stderr , "Erreur dans la fonction sectSegments");
                exit(EXIT_FAILURE);
            }
     
        }
    }


    Voila voila ...

    @+ et merci d'avance

  2. #2
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Salut!

    Quelques trucs en vrac:

    Que sont tes segments AB et CD dans ta démonstration?

    Qu'entends-tu par point d'intersection, tu veux dire que P se trouve sur [AB] inter [CD]?

    Ensuite ta fonction sectSegment prend en paramètres deux points (donc un segment) et les coordonnées du clic et un paramètre infini: que veut dire ce paramètre infini, à quoi sert-il?
    Que fait ta fonction sectSegment avec ces paramètres (quel est son rôle)?

    Sinon, comment passe t'on de savoir si un point est sur un segment à savoir si un point est dans une surface?

    Dans ta boucle, tu auras un problème, i va prendre la valeur 4 et i+1 la valeur 5, or le point n°5 est nul (enfin je ne sais pas si ça pose vraiment problème)

    Désolé si mes questions peuvent te paraître idiotes, mais il me faut plus d'éléments pour comprendre

    HS: Pour faire une capture d'écran, alt+impr ecran c'est plus joli
    Sinon le dessin est joli

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

    Informations forums :
    Inscription : Juillet 2009
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Bonjour à toi , ami insomniaque

    AB est un segment du polygone (autrement dit du contour de la zone de déplacement du joueur ) .
    CD est un segment qui part du point à tester (la ou clique le joueur) et qui va au point "infini" . Le point "infini" est en fait un point dont on est sur qu'il ce trouve bien forcément hors du polygone (très loin ) , ici , dans une fenêtre 800*600 , j'ai mis le point infini à x3000 y4000 , donc , pas de danger
    P est le point d'intersection entre AB et CD (il peut exister ou pas) .

    Le rôle de la fonction sect segment est de renvoyer 1 si section il y a et 0 si section il n'y à pas entre les deux segments .

    oui en effet , il y a une erreur a cet endroit de la fonction .

    je corrige :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          if ( i < nbppoly) // Si i est plus petit que le nombre de point
            sect = sectSegment ( polygone.point[i] , polygone.point[i+1] , clic , infini) ; // On teste le segment i-point suivant
         else if ( i == nbppoly )//Si i est = au nombre de point , alors c'est le drenier point donc on teste avec le premier pour boucler la figure
            sect = sectSegment ( polygone.point[i] , polygone.point[1] , clic , infini) ;
    Cependant , cela ne fonctionne toujours pas ...
    Ici , je teste en cliquant dans le polygone donc , il y auras forcément toujours une intersection donc normalement je devrais pouvoir me déplacer dans le polygone.

    Du moins dans celui que j'ai choisi , au final , la fonction clicPoly testera en fait chaque segment et rajoutera + 1 à un compteur à chaque intersection détectée. Si le chiffre dans ce compteur est impair , on est forcément dedans et si ce chiffre est pair , alors on est dehors .

    Cette fonction renvoie 1 si le point à tester (ici , on envoi le clic de la souris)
    est dans le polygone (de type poly avec 70 point max , largement suffisant) , et 0 si il est dehors .

    Je dois finir par dire que tous cela je l'ai trouver sur le web et que pour ce qui est de la démonstration , je ne la comprend pas totalement ... c'est que je vien juste de terminer ma 3éme moi alors , même avec toute la bonne volonté et la passion du monde , j'ai un peu de mal a tout pigé rien qu'avec des articles trouvé sur le web

    Je vais finir par te remercier pour le compliment sur le dessin et ton intérêt pour mon topic

    @+

  4. #4
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Je suis trop fatigué pour regarder la fonction sectSegment (j'ai quand même compris le principe ) mais pour les boucles c'est pas ça encore:

    Tes points sont stockés dans point[0], ..., point[4]

    Et tu as nbpoly = 5.

    Pour boucler ça serait donc ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          if ( i + 1< nbppoly) // Si i est plus petit que le nombre de point
            sect = sectSegment ( polygone.point[i] , polygone.point[i+1] , clic , infini) ; // On teste le segment i-point suivant
         else if ( i + 1== nbppoly)//Si i est = au nombre de point , alors c'est le drenier point donc on teste avec le premier pour boucler la figure
            sect = sectSegment ( polygone.point[i] , polygone.point[0] , clic , infini) ;
    Sur ce, bonne nuit

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

    Informations forums :
    Inscription : Juillet 2009
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Salut


    EDIT :
    En fait tu a raison , c'est à cause du tableau qui commence à zéro alors que le nbppoly commence à 1
    voici le code un peu commenter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
          if ( i + 1< nbppoly) // Si i+1 est inferieur au nombre de points ,
          //alors , le dernier point n'est pas encore atteint .
            sect = sectSegment ( polygone.point[i] , polygone.point[i+1] , clic , infini) ; // On teste le segment i-point suivant
         else if ( i + 1== nbppoly)//Si i +1 = nombre de point
         // alors ,  le dernier point est attein (il y a un décalage de 1 a cause du tableau qui commence à l'indice 0)
         //On teste donc le dernier point avec le premier pour boucler la figure
            sect = sectSegment ( polygone.point[i] , polygone.point[0] , clic , infini) ;
    Cependant , cela ne fonctionne toujours pas ... ça doit venir de la fonction sectSegment


    Sur ce , encore merci à toi pour ton aide et bonne nuit même si tu dois déjà être coucher en fait

  6. #6
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Dans ce cas-là teste ta fonctoin sectSegment dans des cas simples

    En faisant une recherche je suis tombé sur ce fil:

    http://www.developpez.net/forums/d36...on-2-segments/

    Et plus particulièrement sur cette intervention:

    Je pense que l'algo suivant fonctionne :
    - Tester si les deux extrémités du segment A sont bien de part et d'autre du segment B (avec son équation de droite)
    - Tester si les deux extrémités du segment B sont bien de part et d'autre du segment A (avec son équation de droite)
    Là j'ai pris un papier et un crayon...
    Si mon niveau en maths est pas trop mauvais, ça donne:

    Pour déterminer le côté du segment [AB] duquel se trouve un point P on fait le signe de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [AB].x*[AP].y-[AB].y*[AP].x
    (ça fait 0 si AB et AP sont parallèles)

    où [AB].x désigne la composante selon x du vecteur AB, ...

    Si donc on veut vérifier que les points C et D sont de part et d'autre de [AB] les signes seraient différents et on aurait donc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ([AB].x*[AC].y-[AB].y*[AC].x)*([AB].x*[AD].y-[AB].y*[AD].x) < 0
    Il suffit donc de faire le test aussi avec (A,B) de part et d'autre de [CD] (en interchangeant ci-dessus A et C , D et B) et de vérifier qu'il est aussi négatif, et là tu auras bien intersection.

    Enfin teste toujours si la fonction marche en affichant dans ton jeu les résultat segment par segment, on sait jamais

    Tu auras quand même quelques cas particuliers: si l'un des deux tests donne 0 alors ton segment [P, point infini] passe par un des points du polygone, il faut alors changer ton point infini et tout refaire!

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

    Informations forums :
    Inscription : Juillet 2009
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Salut à toi et désoler de répondre si tard
    j'étais un peu pris ...

    Merci beaucoup pour ton aide , je vais voir de coder ça au plus vite et si je n'y arrive pas , je reviendrais poster ici ... mais je vais faire mon maximum pour y arriver tout seul .

    !encore merci

Discussions similaires

  1. Réponses: 5
    Dernier message: 26/10/2009, 23h03
  2. [IA] jeux type Rocks and diamond
    Par yoshï dans le forum Intelligence artificielle
    Réponses: 9
    Dernier message: 22/02/2008, 10h56
  3. Réponses: 9
    Dernier message: 22/02/2005, 15h49
  4. Limiter les déplacement de la souris a la fenetre
    Par Mathieu.J dans le forum OpenGL
    Réponses: 22
    Dernier message: 11/06/2004, 12h55
  5. Limiter le déplacement de la souris
    Par el_bouleto dans le forum C++Builder
    Réponses: 4
    Dernier message: 08/11/2002, 23h56

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