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 :

[C] Tableau bidimensionnel & Collisions : problème !


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut [C] Tableau bidimensionnel & Collisions : problème !
    Bonjour à tous !

    Je m'occupe actuellement de la création d'un jeu en SDL. Pour gérer les collisions personnage/décor, j'ai recours à un tableau bidimensionnel, en int, dont les cellules vont prendre la valeur 0 en absence de sprite (zone walkable) et 1 en cas de sprite (zone non walkable).

    Mes collisions fonctionnent bien, très bien ... à tel point qu'il y en a quand il n'en faut pas.

    J'ai cherché l'origine du problème, et je me rends compte que lors du chargement de la map (par lecture de fichier) et par la même occasion lors du changement des valeurs du tableau ... certaines cellules du tableau prennent la valeur 1 alors qu'elles ne correspondent pas à une sprite (ni à l'affichage, ni dans le fichier ...).

    J'ai donc testé le tableau avant l'affichage de la map, et tout était bien initialisé à 0. J'en ai donc conclu que le problème venait de mon algo qui permet de détecter sur quelle(s) cellule(s) se trouvent les sprites.

    (Je précise que la taille des sprites est un multiple de la taille de chaque "bloc")

    Voici mon code, qui pourtant me semble juste, mais qui semble poser problème :

    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
     
     
    void affichageMap(SDL_Surface *ecran, SDL_Surface *background, FILE* map, SDL_Surface *spriteChoisi[], int carte[][NB_BLOCS_H])
    {
    //---- Déclaration des variables -----------------------------------------------
    SDL_Rect position;
     
    int choixSprite = 0,
        position_x = 0,
        position_y = 0,
        largeur_sprite = 0,
        hauteur_sprite = 0;
     
    int l,h;
    //------------------------------------------------------------------------------
     
    SDL_BlitSurface(background, NULL, ecran, NULL);
     
    //---- On lit le contenu du fichier & on affiche les sprites -------------------
    if(map == NULL)
    {
        exit(EXIT_FAILURE);
    }
     
    while(!feof(map))
    {
        fscanf(map, "%d %d %d %d %d\n", &choixSprite, &position_x, &position_y, &largeur_sprite, &hauteur_sprite);
     
        position.x = position_x;
        position.y = position_y;
     
        SDL_BlitSurface(spriteChoisi[choixSprite], NULL, ecran, &position);
     
        for(l = 0 ; l < (largeur_sprite / LARGEUR_BLOC) ; l++)
        {
            for(h = 0 ; h < (hauteur_sprite / HAUTEUR_BLOC) ; h++)
            {
                carte[(position.y / HAUTEUR_BLOC) + h][(position.x / LARGEUR_BLOC) + l] = 1;
            }
        }
    }
    fclose(map);
    }
    Je précise que l'affichage des sprites ne pose aucun problème, et que les collisions avec les sprites non plus ... le problème est qu'il y a aussi des collisions dans le vide ^^.

    Pour illustrer le problème :

    Voilà un exemple d'affichage des sprites :

    Affichage

    Voilà les valeurs du tableau correspondant ... je ne comprends vraiment pas :

    Valeurs du tableau

    Gloups ?

    Merci d'avance pour votre aide !

    PS : si c'est pas clair, dites-le, je sais pas si c'est très compréhensible ^^

  2. #2
    Membre chevronné
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Par défaut
    Hello,

    Citation Envoyé par Pingouin
    Bonjour à tous !

    [enlevé]

    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
     
     
    void affichageMap(SDL_Surface *ecran, SDL_Surface *background, FILE* map, SDL_Surface *spriteChoisi[], int carte[][NB_BLOCS_H])
    {
    //---- Déclaration des variables -----------------------------------------------
    SDL_Rect position;
     
    int choixSprite = 0,
        position_x = 0,
        position_y = 0,
        largeur_sprite = 0,
        hauteur_sprite = 0;
     
    int l,h;
    //------------------------------------------------------------------------------
     
    SDL_BlitSurface(background, NULL, ecran, NULL);
     
    //---- On lit le contenu du fichier & on affiche les sprites -------------------
    if(map == NULL)
    {
        exit(EXIT_FAILURE);
    }
     
    while(!feof(map))
    {
       fscanf(map, "%d %d %d %d %d\n", &choixSprite, &position_x, &position_y, &largeur_sprite, &hauteur_sprite);
    Ici, déjà il y a un souci => feof() renvoie autre chose que 0 quand l'indicateur de fin de fichier a effectivement mis à jour. Autrement dit, avant que ta condition soit vraie, le fscanf() aura probablement échoué avant. feof() et ferror() sont des fonctions après une boucle de lecture, et non pas en tant que condition d'arrêt de boucle de lecture [Tu es le 2nd aujourdh'ui à te faire avoir ].
    Par contre, vérifier que fscanf() a réussi toutes ses conversions, il eut été bon de le faire.

    Donc la boucle de lecture peut être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    while (fscanf(map, "%d %d %d %d %d\n", &choixSprite, &position_x, &position_y, &largeur_sprite, &hauteur_sprite) == 5 ) {
         /* do something */
    }
     
    if (!feof(map) || ferror(map)
    {
        /* error while reading*/
    }
    Ceci dit, ce n'est pas encore parfait. En effet dans la spécification de format du fscanf(), tu as explicité le fait de rencontrer un '\n'. Si il n'y a pas de newline à la fin du fichier, tu peux ne pas lire la dernière ligne. Et si il y a une ligne vide sans rien (des '\n' à la suite), il y aura aussi un échec de lecture avec fscanf() (même sans '\n' dans la spécif de format remarque). C'est pour cela qu'il vaut mieux utiliser fgets() combiné avec sscanf(), le fgets() permettant de contrôler la lecture ligne par ligne du fichier, et le contrôle du retour de sscanf() permettant de décider entre continuer la lecture du fichier en passant à la ligne suivante ou pas.

    Citation Envoyé par Pingouin
    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
     
      position.x = position_x;
        position.y = position_y;
     
        SDL_BlitSurface(spriteChoisi[choixSprite], NULL, ecran, &position);
     
        for(l = 0 ; l < (largeur_sprite / LARGEUR_BLOC) ; l++)
        {
            for(h = 0 ; h < (hauteur_sprite / HAUTEUR_BLOC) ; h++)
            {
                carte[(position.y / HAUTEUR_BLOC) + h][(position.x / LARGEUR_BLOC) + l] = 1;
            }
        }
    }
    fclose(map);
    }
    Je précise que l'affichage des sprites ne pose aucun problème, et que les collisions avec les sprites non plus ... le problème est qu'il y a aussi des collisions dans le vide ^^.

    Merci d'avance pour votre aide !

    PS : si c'est pas clair, dites-le, je sais pas si c'est très compréhensible ^^
    Je n'ai fait que corriger le pb avec feof(), maintenant, cela m'étonne que ça puisse être à l'origine de ton problème original.

    A+

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut
    Merci de t'intéresser à mon problème ... j'ai rectifié la fonction concernant le feof, par contre pour le fgets, il faut que je me renseigne car je ne vois pas comment faire. Mais je ne pense pas que ça change le problème, puisque l'affichage s'effectue sans problème, donc la lecture aussi ... enfin je pense !

    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
     
    void affichageMap(SDL_Surface *ecran, SDL_Surface *background, FILE* map, SDL_Surface *spriteChoisi[], int carte[][NB_BLOCS_H])
    {
    //---- Déclaration des variables -----------------------------------------------
    SDL_Rect position;
     
    int choixSprite = 0,
        position_x = 0,
        position_y = 0,
        largeur_sprite = 0,
        hauteur_sprite = 0;
     
    int l,h;
    //------------------------------------------------------------------------------
     
    //---- Affichage du Background -------------------------------------------------
    SDL_BlitSurface(background, NULL, ecran, NULL);
    //------------------------------------------------------------------------------
     
    //---- On lit le contenu du fichier & on affiche les sprites -------------------
    while( fscanf(map, "%d %d %d %d %d\n", &choixSprite, &position_x, &position_y, &largeur_sprite, &hauteur_sprite) == 5 )
    {
        position.x = position_x;
        position.y = position_y;
     
        SDL_BlitSurface(spriteChoisi[choixSprite], NULL, ecran, &position);
     
        for(l = 0 ; l < (largeur_sprite / LARGEUR_BLOC) ; l++)
        {
            for(h = 0 ; h < (hauteur_sprite / HAUTEUR_BLOC) ; h++)
            {
                carte[(position.y / HAUTEUR_BLOC) + h][(position.x / LARGEUR_BLOC) + l] = 1;
            }
        }
    }
     
    if (!feof(map) || ferror(map))
    {
        exit(EXIT_FAILURE);
    }
     
    fclose(map);
    }

  4. #4
    Membre chevronné
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Par défaut
    Citation Envoyé par Pingouin
    Merci de t'intéresser à mon problème ... j'ai rectifié la fonction concernant le feof, par contre pour le fgets, il faut que je me renseigne car je ne vois pas comment faire. Mais je ne pense pas que ça change le problème, puisque l'affichage s'effectue sans problème, donc la lecture aussi ... enfin je pense !
    Pour le fgets(), il faut juste un tampon d'accueil assez grand pour une ligne.

    Exple :
    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
     
    int rc = 0;
    char ligne[255 + 1]; /* 255 caracteres 'valides' max + '\0' */
     
    while ( fgets(ligne, sizeof(ligne)/sizeof(*ligne), map) )
    {
        if ( (rc = sscanf(ligne, "%d %d %d %d %d", &choixSprite, &position_x,
                             &position_y, &largeur_sprite, &hauteur_sprite))  != 5 )
        {
           /* on est dans le cas échec sscanf() */
           if ( rc == EOF ) { 
               /* on est dans le cas échec sscanf() à cause erreur lecture 
                * avant conversion => on arrête
                */
               break;
           }
           else {
               /* on est dans le cas échec sscanf() à cause  
                * conversion non réussie => on continue (ligne vide peut être)
                */ 
               continue;
           }
        }
        /* TRAITEMENT */
    }
     
    if (!feof(map) || ferror(map))
    {
        /* erreur */
    }
    Ton pb original doit être situé ailleurs.

    A+

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut
    En fait pour le fgets merci je me suis débrouillé ^^ ...

    Revenons-en au problème ... je ne sais pas si tu as vu les 2 illustrations du problème que j'ai données en lien en EDIT de mon premier post.

    Ce qui m'amène à dire que le problème vient de cet algo, c'est qu'avant l'appel de cette fonctionn affichageMap, le tableau est bel et bien initialisé à 0, j'ai même enregistré les valeurs dans un fichier pour vérifier.

    Juste après cette fonction (rien ne s'effectue d'autre que cette fonction donc), le problème apparaît, cf les illustrations ....

    C'est quand même très bizarre et depuis ce matin mes quelques pauvres neurones s'entrechoquent et s'emmêlent sans voir l'issure du problème ! ... c'est vraiment déroutant !

  6. #6
    Membre chevronné
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Par défaut
    Citation Envoyé par Pingouin
    En fait pour le fgets merci je me suis débrouillé ^^ ...

    Revenons-en au problème ... je ne sais pas si tu as vu les 2 illustrations du problème que j'ai données en lien en EDIT de mon premier post.

    Ce qui m'amène à dire que le problème vient de cet algo, c'est qu'avant l'appel de cette fonctionn affichageMap, le tableau est bel et bien initialisé à 0, j'ai même enregistré les valeurs dans un fichier pour vérifier.

    Juste après cette fonction (rien ne s'effectue d'autre que cette fonction donc), le problème apparaît, cf les illustrations ....

    C'est quand même très bizarre et depuis ce matin mes quelques pauvres neurones s'entrechoquent et s'emmêlent sans voir l'issure du problème ! ... c'est vraiment déroutant !
    Des idées,

    Vérifier que 'carte' est bien à zéro partout avant modification dans la fonction.

    EDIT:

    Des choses qu'on ne voit pas de suite (cause bière et foot peut-être )

    Est-ce cohérent ?

    Je vois en paramètre formel de fonction,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int carte[][NB_BLOCS_H]
    Puis après dans l'indexation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    carte[(position.y / HAUTEUR_BLOC) + h][(position.x / LARGEUR_BLOC) + l]
    J'ai un doute (par rapport au nom NB_BLOCS_H et ce qui est fait après, ce n'est pas bon => confusion "lignes"/"colonnes") . Il faut voir aussi comment est déclaré 'carte' en amont.

    FIN EDIT.

    Tu as aussi la variable,

    SDL_Rect position;

    et tu mets à jour seulement 2 de ses membres,

    position.x = position_x;
    position.y = position_y;

    Peut-être vaut-il mieux complètement renseigner la structure position avant appel de SDL_BlitSurface(), en donnant les dimensions d'un sprite ?

    position.x = position_x;
    position.y = position_y;
    position.w = largeur_sprite;
    position.h = hauteur_sprite;

    A+

  7. #7
    Membre émérite Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Par défaut
    Citation Envoyé par Foobar1329
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (!feof(map) || ferror(map))
    {
        /* error while reading*/
    }
    Ne serait-ce pas plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (feof(map) || ferror(map))
    {
        /* error while reading*/
    }

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par crocodilex
    Ne serait-ce pas plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (feof(map) || ferror(map))
    {
        /* error while reading*/
    }
    Ben non.

    http://emmanuel-delahaye.developpez....s.htm#fichiers

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut
    Oula il s'en est passé des choses ici !

    Alors, finalement qui a raison pour le feof() ?

    Bon sinon, j'ai vérifié pour l'histoire des NB_BLOCS_L et NB_BLOCS_H et ça me semble juste .... pour "preuve" les collisions fonctionnent, même s'il s'en greffent d'autres où il n'en faut pas, et si je change abscisse/ordonnée dans mon algo, j'obitens les collisions avec une rotation de 90° ^^ ! Donc c'est bien dans ce sens que ça fonctionne.

    Je sais pas si vous avez vu les liens que j'ai mis en EDIT de mon premier post :

    Affichage

    Carte des valeurs du tableau correspondant

    Ou les 2 l'un sur l'autre :

    Affichage & Tableau


    Mais c'est ça qui m'achève ... où est le problème ? à la lecture alors peut-être ? et on en reviendrait au feof() ?


    PS : je mets même le fichier de la map qui est lu au cas où :

    5.map

  10. #10
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Pingouin
    Alors, finalement qui a raison pour le feof() ?
    C'est simple : dans la plupart des cas, on ne l'utilise pas. Par contre on detecte la fin de lecture en surveillant la valeur retournée par la fonction de lecture.

    Si on doit utiliser feof(), c'est uniquement pour déterminer a posteriori quelle est la cause de la fin de lecture. C'est rarement utile...

  11. #11
    Membre chevronné
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Par défaut
    Hello,

    Citation Envoyé par crocodilex
    Ne serait-ce pas plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (feof(map) || ferror(map))
    {
        /* error while reading*/
    }
    Non, dans le cas présenté, je voulais traiter comme cas d'erreur le fait de ne PAS AVOIR rencontré la fin de fichier pendant la lecture.

    Donc c'est bien !feof(fichier).

    A+

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Non, car feof() n'est pas initialisé tant que fscanf()/fgets()/etc. n'a pas renvoyé d'erreur.
    En clair, feof() pourrait être non-nul avant la fin du fichier.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 19
    Par défaut
    Lool moi je ne suis qu'un pauvre débutant, et je me perds dans vos explications ^^ !

    De toute façon je ne pense pas que le problème puisse venir de là ... mais bon pourquoi pas ?

  14. #14
    Membre émérite Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Par défaut
    Citation Envoyé par Foobar1329
    Hello,
    Non, dans le cas présenté, je voulais traiter comme cas d'erreur le fait de ne PAS AVOIR rencontré la fin de fichier pendant la lecture.

    Donc c'est bien !feof(fichier).

    A+
    Tout a fait exact, je ne l'avais pas vu sous cette angle... Maudit feof()....#%&^$§!!

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 22/05/2007, 12h21
  2. Tableau bidimensionnel de Vector
    Par j0o0 dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 05/05/2007, 19h51
  3. Affichage tableau bidimensionnel
    Par LhIaScZkTer dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 22/11/2006, 16h17
  4. pb tableau bidimensionnel en dynamique
    Par silencer dans le forum C
    Réponses: 4
    Dernier message: 18/11/2006, 20h17
  5. tableau bidimensionnels comment faire?
    Par yvon_huynh dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 18/08/2006, 08h15

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