Minecraft en C.
Répondre à la discussion
Affichage des résultats 1 à 26 sur 26

Minecraft en C.



  1. #1
    Cech

    Minecraft en C.


    ------

    Salut à tous !

    J'essaie de faire un petite version de Minecraft en 2D programmée en langage C.

    J'ai rencontré un souci sur une fonction dont le but est de faire déplacer un '@' à droite dans un tableau de caractères à deux dimensions nommé terrain :
    Si la case à droite (vers laquelle je vais) contient de l'air, comme on a :
    typedef enum
    Code:
    {
        air, wood, soil, rock, water, gem, iron, fire, grass, flower, plank,
        money, gold, ashes, unknown
    } Materiau;

    alors air vaut 0 et je peux déplacer vers la droite, je peux aussi sauter par dessus une case rempli si jamais il y a de l'air au dessus.

    Enfin si jamais il y a un trou là où j'avance, je tombe.

    L' '@' est en fait le caractère qui représente la position codée par :
    typedef struct
    Code:
    {
        int x;
        int y;
    } Personnage;

    Voici la bête : Personnage mouvement_droite(Terrain terrain, Personnage p)
    Code:
    {
        if(p.x == L_TERRAIN-1){return p;}
        if(terrain[p.y][p.x+=1]!= 0){
            if(terrain[p.y+=1][p.x-=1] == 0){p.y+=1;p.x-=1;}
            else {return p;}
            return p;
        }
        if(terrain[p.y][p.x+=1]== 0){
        int i=0; do{i++;}while(terrain[p.y+=1][p.x-=i]==0);
        p.x-=i;p.y+1; return p;
        }
    }

    Vous voulez d'autres infos ? Qu'en dites vous ? Moi je dis que ma fonction en fait rien !! Je ne comprends pas, je vais me suicider avec le cable de ma sourie

    Voici un terrain si ça vous intéresse !

    void cree_terrain1(Terrain terrain)
    {
    int i,j;
    char t[7][21] =
    {
    " ",
    " TTT #",
    " T ##",
    "==~~~~===========###",
    "===~~==========###+#",
    "=========#+#==#g#+##",
    "#####g##############"
    };
    for (i = 0; i < H_TERRAIN; i++)
    for (j = 0; j < L_TERRAIN; j++)
    terrain[i][j] = char2Materiau(t[i][j]);
    }

    On note ici que char2Materiau est juste là pour associer un caractère à un numéro bref !!!

    -----
    Dernière modification par JPL ; 04/02/2016 à 23h05. Motif: Ajout de la balise Code (#)

  2. #2
    Chanur

    Re : Minecraft en C.

    Bonjour,

    Code:
    {
        if(p.x == L_TERRAIN-1){return p;}
        if(terrain[p.y][p.x+=1]!= 0){
            if(terrain[p.y+=1][p.x-=1] == 0){p.y+=1;p.x-=1;}
            else {return p;}
            return p;
        }
    Je trouve assez difficile de lire un code qui met une incrémentation dans l'indice d'un tableau dans un test.
    Tu ferais mieux d'écrire :
    Code:
    {
        if(p.x == L_TERRAIN-1){return p;}
        p.x ++;
        if(terrain[p.y][p.x]!= 0)
            {
            p.y ++;
            p.x --;
            if(terrain[p.y][p.x] == 0){p.y ++; p.x --;}
            else {return p;}
            return p;
            }
    Je trouve qu'on voit nettement mieux ce qui se passe.
    Et je trouve ça complètement absurde ...
    On fait avancer le personnage. Puis, s'il est sur une case différente de 0, on le fait reculer et descendre. Puis, s'il est sur une case valant 0, on le fait encore reculer et descendre.
    C'est à dire que s'il y a une case non nulle à droite du personnage, on le fait descendre et s'il est alors sur une case 0 on le refait descendre et se déplacer vers la gauche ...
    Moi je testerais ce qu'il y a autour du personnage avant de le déplacer.

    La deuxième partie de la fonction est pire : à chaque itération de la boucle on déplace le personnage de i cases.

    Le tout sans jamais tester si on dépasse le tableau (tu vérifies juste, au début, que x n'est pas au bord à droite, mais comme tu modifies plusieurs fois x dans les deux sens, rien n'impose qu'il reste entre 0 et L_TERRAIN-1)

    Au passage, pourquoi définir une enum, si tu ne t'en sert pas ?
    Dernière modification par Chanur ; 05/02/2016 à 00h31.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  3. #3
    Cech

    Re : Minecraft en C.

    Salut !

    1) J'aime bien l'écriture x+=1 parce que je peux aussi écrire x+=8 c'est plus général (c'est mon côté matheux )

    2) Aïe ! J'ai tout fait à l'envers alors ...

    "Moi je testerais ce qu'il y a autour du personnage avant de le déplacer."
    Hum intéressant.

    Moi en fait j'ai remarqué en testant à la main le programme que p.x++ faisait descendre le personnage vers le bas ! Et p.y++ faisait avant le personnage vers la droite.
    Contre les axes sont inversés ! Et le sens de l'axes des x est vers le bas j'en ai déduit.


    3) Je me sers de l'énum au cours du programme ici, on a juste air qui vaut 0.

  4. #4
    Jack
    Modérateur

    Re : Minecraft en C.

    1) J'aime bien l'écriture x+=1 parce que je peux aussi écrire x+=8 c'est plus général (c'est mon côté matheux )
    La remarque de Chanur tenait moins dans l'utilisation de l'opérateur += que dans le fait que tu l'utilisais dans l'indice du tableau.

  5. A voir en vidéo sur Futura
  6. #5
    Cech

    Re : Minecraft en C.

    Je me rend compte que mon programme est trop personnel pour que vous pussiez m'aider réellement, faudrait que vous l'ayez fait avec moi... Veillez m'excuser pour le post !

  7. #6
    Chanur

    Re : Minecraft en C.

    C'est surtout que tu ne tiens pas compte des observations ...
    Alors ça ne donne pas vraiment envie d'aller plus loin.

    Citation Envoyé par Chanur Voir le message
    La deuxième partie de la fonction est pire : à chaque itération de la boucle on déplace le personnage de i cases.
    Ou encore, suppose que le premier test soit négatif. comme tu as quand même déplacé le personnage, le deuxième test se fait à x+2 (c'est à dire à une position dont tu ne teste même pas si elle dépasse le terrain de jeu) ...

    Tout ce que tu as répondu c'est "Hum intéressant".

    Ou bien tu as corrigé ton programme en en tenant compte et on ne peut rien faire pour toi tant que tu ne postes pas la version modifiée, ou bien tu ne l'as pas corrigé et on ne peut rien faire pour toi ...

    (@ Jack: je n'ai pas répondu parce que tu as raison, bien sûr, mais j'aurais peut-être dû le préciser.)
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  8. #7
    Cech

    Re : Minecraft en C.

    Merci Chanur pour votre patience.

    Et oui c'est vrai j'ai modifié mon programme en tenant compte de vos observations mais j'ai pas envie de vos faire perdre votre temps.
    Ceci dit voici mon nouveau
    Code:
    Personnage mouvement_droite(Terrain terrain, Personnage *p)
    {
        if(terrain[(*p).y+=1][(*p).x] != air){
                if(terrain[(*p).y+=1][(*p).x-=1] == air){
                    (*p).x-=1; (*p).y+=1;
                }
            }
        if(terrain[(*p).y+=1][(*p).x] == air){
            do{
                    (*p).x+=1;
            }while(terrain[(*p).y+=1][(*p).x+=1] == air);
            (*p).y+=1;
        }
    }

    Je vous rappelle que (*p).y+=1 fait que mon '@' se déplace à droite dans le tableau et que (*p).x+=1 fait que mon '@' descend d'une case dans le tableau.

    Je vous rappelle que les terrains sont des tableaux de Matériaux un type que j'ai crée.

  9. #8
    Cech

    Re : Minecraft en C.

    Cette fonction fait disparaître mon '@' du tableau.

  10. #9
    pm42

    Re : Minecraft en C.

    Normal, elle passe son temps à incrémenter les valeurs, p.x même si les if renvoient false et à ne jamais les remettre à la valeur initiale. Idem à l'intérieur des while
    Elle déclare également qu'elle renvoie un Personnage ce qu'elle ne fait pas, etc.


    On ne programme jamais comme cela justement parce qu'il est quasiment impossible d'avoir du code correct : il faudrait utiliser 2 variables locales, x et y, mettre p->x et p->y dedans au début, trouver leur valeur finale et les remettre dans p->x et p->y.
    Au passage, utiliser les syntaxes standard avec ++, --, -> au lieu de (*p) serait un plus.


    Bref, votre code n'est pas "trop personnel" : il est juste faux.

  11. #10
    Cech

    Re : Minecraft en C.

    Pouvez vous m'en dire plus ? Là je ne comprends pas mes erreurs même si je comprends qu'il y en a un paquet.

    Pour Personnage, j'ai remarquer que si je tapais juste (*p).y+=1 dans la fonction elle me faisait à droite donc j'ai continué sur cette voie.

    Donc je ne vois pas la différence entre utiliser x et y si x = p.x et y = p.y. Que voulez vous dire ?

  12. #11
    Chanur

    Re : Minecraft en C.

    Citation Envoyé par Cech Voir le message
    Code:
    Personnage mouvement_droite(Terrain terrain, Personnage *p)
    {
        if(terrain[(*p).y+=1][(*p).x] != air){
                if(terrain[(*p).y+=1][(*p).x-=1] == air){
                    (*p).x-=1; (*p).y+=1;
                }
            }
        if(terrain[(*p).y+=1][(*p).x] == air){
            do{
                    (*p).x+=1;
            }while(terrain[(*p).y+=1][(*p).x+=1] == air);
            (*p).y+=1;
        }
    }

    Je vous rappelle que (*p).y+=1 fait que mon '@' se déplace à droite dans le tableau et que (*p).x+=1 fait que mon '@' descend d'une case dans le tableau.
    C'est simple, il faut analyser ce qui se passe en détail, dans un cas qui ne marche pas.
    Le plus facile est de le faire avec un debugger en pas par pas, ou avec du papier et un crayon :

    Supposons que p->y ait la plus grande valeur possible (L_TERRAIN-1) :
    if(terrain[(*p).y+=1][(*p).x] != air) pas la peine d'aller plus loin, on est en train de tester une valeur en dehors du tableau puisque p->y+1 vaut L_TERRAIN

    Supposons que p->y == L_TERRAIN -2 et que terrain[p->y +1][p->x] == air
    if(terrain[(*p).y+=1][(*p).x] != air) : faux donc on passe au test suivant (après avoir incrémenté p->y)
    if(terrain[(*p).y+=1][(*p).x] == air) pas la peine d'aller plus loin, on est en train de tester une valeur en dehors du tableau puisque p->y+2 vaut L_TERRAIN

    Il serait déjà intéressant de corriger ça.
    Mais en fait le problème est plus profond : tu as écris :
    Si la case à droite (vers laquelle je vais) contient de l'air, je peux déplacer vers la droite,
    je peux aussi sauter par dessus une case rempli si jamais il y a de l'air au dessus.
    Enfin si jamais il y a un trou là où j'avance, je tombe.

    Il faut commencer, sur le papier, par traduire ça clairement en terme de calcul de coordonnées et de tests de valeurs.
    Après avoir décrit précisément l'algorithme, il est très facile de la traduire dans n'importe quel langage.
    Travailler dans l'autre sens : écrire un machin approximatif et le debugger jusqu'à ce qu'il marche, ça ne peut fonctionner que dans des cas très simples et ça prend beaucoup plus de temps.

    La, tel que tu l'as écrit, ça ne correspond PAS à ta description initiale :
    tu as programmé :
    je me déplace vers la droite.
    si la case sur laquelle je suis ne contient pas de l'air, je me déplace vers la droite et vers le haut.
    si la case sur laquelle je suis contient de l'air je me déplace de deux cases vers la droite et d'une case vers le bas tant que la case où je suis contient de l'air.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  13. #12
    Cech

    Re : Minecraft en C.

    En tenant compte de vos remarque j'ai effectué pas mal de changement.

    Selon le conseil de pm42, j'ai utilisé des variables.

    Selon les conseils Chanur, j'ai fait un schéma et j'ai remarque que si l'on voit le tableau comme une matrice alors les coefficients sont exactement (p.x ; p.y). Du coup j'étais certain de mon coup quand j'ai écrit ce
    Code:
    Personnage mouvement_droite(Terrain terrain, Personnage *p)
    {
        int A=0,B=0,a= (*p).x, b=(*p).y;
        if ((b >= L_TERRAIN-1) || (a >= H_TERRAIN -1)){return *p;}
        if(terrain[a][b+=1] != air){
                if(terrain[a-=1][b+=1] == air){
                    A = (a-1); B = (b+1);
                }((*p).x)=A; ((*p).y) = B;
        }
        if(terrain[a][b+=1] == air){
            B = (b+1); int i=1;
            while(terrain[a+=i][b+=1] == air){
                    A = a+1;
                    i++;
            }((*p).x)=A; ((*p).y)=B;
        }
        printf("\na = %d et b = %d\n",a,b);
        printf("\nCoordonnee :\nEn x : %d\nEn y : %d",((*p).x),((*p).y));
    }
    J'ai aussi rajouté des printfs pour essayer de comprendre la machine... Mais je n'y comprends vraiment rien ! Je crois que j'ai crée une entité vivantes qui se déplace selon ses envies !

    Quelques chiffres.
    Ma position d'origine (5,3)
    Ma position après mouvement est (0,6) alors que j'aurais du obtenir (5,4) en effet il y a de l'air dans cette case est pas de trou.
    Et j'ai a = b= 6.

  14. #13
    Cech

    Re : Minecraft en C.

    Je pense sincérement que faire terrain[a++][b++] augmente la valeur de a et de b. Il faut retirer à chaque fois.

  15. #14
    Cech

    Re : Minecraft en C.

    Je viens de le faire y'a du mieux. Mais comme le dit chanur ça sert à rien de bidouiller faut tout reprendre à 0.

    Je vais m'y atteler plus tard.

  16. #15
    pm42

    Re : Minecraft en C.

    Citation Envoyé par Cech Voir le message
    Selon le conseil de pm42, j'ai utilisé des variables.
    Ca ne sert à rien si tu passes ton temps à les incrémenter sur place.

    if(terrain[a][b+=1] != air){

    est une aberration.
    Tu devrais faire
    if(terrain[a][b+1] != air){

    et là le traitement associé : éventuellement, changer a ou b, faire autre chose, etc.
    Autre chose : on ne met jamais 2 variables avec le même nom, l'une en majuscules, l'autres en minuscule comme tes A et a.

    Et finalement, il te manque toujours des return.

  17. #16
    Cech

    Re : Minecraft en C.

    Merci vous avez tapé juste, c'était bête de fonctionner ainsi, if(terrain[a][b+1] != air) marche beaucoup mieux.

    Voici le code qui fonctionne :
    Code:
    {
        int a = (*p).x, b =(*p).y;
        if ((b >= L_TERRAIN-1) || (a >= H_TERRAIN -1)){return *p;}
        if(terrain[a][b+1] != air){
                if(terrain[a-1][b+1] == air){
                    ((*p).x) = (a-1); ((*p).y) = (b+1);
                }
        }
        if(terrain[a][b+1] == air){
                int i=1; while(terrain[a+i][b+1] == air){
                    ((*p).x) = (a+i);
                    i++;
            }
            ((*p).y) = (b+1);
        }
        printf("\na = %d et b = %d\n",a,b);
        printf("\nCoordonnee :\nEn x : %d\nEn y : %d",((*p).x),((*p).y));
    }
    C'était la première fois que j'utilisais les pointeurs sur une structure, c'était dur pour moi, j'en ai perdu la raison un peu lol mais grâce à vous, je me suis remis dans le droit chemin et actuellement je ma fonction fait bien le boulot. Je vais pouvoir continuer le projet ! Héhé

    Merci.

  18. #17
    Cech

    Re : Minecraft en C.

    J'ai fait encore une modification parce que je saute sur des case vides en traversant des cases pleines au dessus de ma tête.
    Par contre que puis-je renvoyer ? (J'ai lue que ma fonction ne renvoie rien, et je l'avoue). Vu le type de la fonction je devrais renvoyer des coordonnées, mais j'ai construit ma fonction pour quelle modifie directement les coordonnées.

    Le type Personne m'indique plutôt comment l'utiliser par la suite...
    Dernière modification par Cech ; 07/02/2016 à 13h14.

  19. #18
    Chanur

    Re : Minecraft en C.

    Citation Envoyé par Cech Voir le message
    Merci vous avez tapé juste, c'était bête de fonctionner ainsi, if(terrain[a][b+1] != air) marche beaucoup mieux.
    Je me trompe peut-être, mais j'ai l'impression que tu ne comprends pas ce que tu fais ?

    Tu comprends la différence entre if(terrain[a][b+1] != air) et if(terrain[a][b+=1] != air) ?
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  20. #19
    pm42

    Re : Minecraft en C.

    Citation Envoyé par Cech Voir le message
    Par contre que puis-je renvoyer ? (J'ai lue que ma fonction ne renvoie rien, et je l'avoue). Vu le type de la fonction je devrais renvoyer des coordonnées, mais j'ai construit ma fonction pour quelle modifie directement les coordonnées.
    Tel quel, déclare ta fonction comme void et ne renvoie rien. Tu modifies sur place.
    Autre solution : ta fonction reçoie des coordonnées, ne les modifie pas et renvoie les nouvelles.

    La 2nd solution est un peu plus lente et consommatrice en ressources mais plus propre.

  21. #20
    Cech

    Re : Minecraft en C.

    Chanur oui je connais la différence, mais j'avoue que je l'avais un peu oublié durant ma phase de travail. Je sais pas pourquoi, je pense que c'est utiliser (*p).x pour la première fois qui m'a fait péter les plombs en effet j'ai remarqué *p.x+1 ne fonctionnait pas du coup ça m'a gravement atteint je suppose. Mais cette dur épreuve passer je me sens plus à l'aise avec les pointeurs sur les structures.

    To be continued.

    Ok merci pmp42. Je pense que c'est la deuxième solution que le prof atteint de moi puisqu'il passe p en argument, je lui demanderais son avis, mais j'aimerais bien garder la mien, car elle me fait apprendre les pointeurs, même si on l'a pas encore vu en cours (mais bientôt )

  22. #21
    Jack
    Modérateur

    Re : Minecraft en C.

    Je te propose d'abandonner la notation (*p).x pour celle-ci qui est plus conventionnelle: p->x

  23. #22
    Cech

    Re : Minecraft en C.

    Ca marche je vais modifier le code.

  24. #23
    bisou10

    Re : Minecraft en C.

    Quel torchon ton code ! Tu ne peux pas t'y retrouver, désolé.

    Ca n'a RIEN avoir avec le syntaxic sugar que tu utilises, ta boucle est toute bancale. Reprends ton algo, reprends tes fonctions.

    Détrompe toi, ce n'est pas un projet trop personnel en terme de complexité, la majorité des intervenants qualifiés de ce forum lisent et pondent du code à longueur de journée, alors des fonctions de 10 lignes, faut s'accrocher pour qu'elles nous semblent hors de portée

  25. #24
    Cech

    Re : Minecraft en C.

    Je disais ça parce que je fais souvent appel à des fonctions que j'ai crée avant et faudrait vous donnez tout le code, rien à voir avec de la compétence .

    J'aimerais modifier ma boucle infini pour la quitter lorsque j'appuie sur la touche q du clavier :
    Code:
     while (1){
            printf("Déplacement (j=gauche, l=droite, q=quitter)?\n");
            c = getchar();
            while ((getchar() != '\n') && (getchar()!='q'));
            if(c == 'l'){mouvement_droite(terrain3,&p);}
            if(c == 'j'){mouvement_gauche(terrain3,&p);}
            affiche_monde(terrain3,p);
        }
    Quand dite vous ? Comment dois-je m'y prendre ?
    Dernière modification par Cech ; 13/02/2016 à 08h15.

  26. #25
    pm42

    Re : Minecraft en C.

    Ta 2nde boucle while est sans fin si on tape autre chose que 'q' ou '\n'.
    Et même dans ce cas là, tu n'as pas de code qui permet de sortir du while(1) initial...

    Et getchar n'est pas la fonction à utiliser pour un jeu à cause de la bufferisation qui va obliger l'utilisateur à taper un retour chariot pour que ton code le recoive. Lequel retour chariot sera ensuite traité et interprété par ton code comme une volonté de sortir (même si en fait il déclenche une boucle sans fin).

    Je suggèrerais bien plus d'efforts, de lecture et d'utilisation d'un débugger et moins de questions élémentaires sur les forums si tu veux progresser.

  27. #26
    Chanur

    Re : Minecraft en C.

    Je te suggère de te documenter sur les fonctions de conio.h (si tu es sous Windows) :
    - getche() qui fonctionne comme getchar, mais n'attend pas le retour chariot
    - getch() qui fonctionne comme getche() mais sans afficher le caractère saisi
    - kbhit(), non bloquante, qui retourne 1 s'il y a un caractère en attente dans le buffer clavier, 0 sinon.

    Par exemple la séquence : while (kbhit()) getch(); vide silencieusement le buffer clavier.

    Attention, ces fonctions sont spécifique Windows et ne sont pas portables (encore que MinGW les intègre sûrement...).
    Elle sont assez peu pratiques pour les touches spéciales (flèches de direction, touche Control, ...) qui génèrent deux "caractères" successifs.

    Sinon, la façon la plus simple de gérer le clavier me semble être :
    Code:
    fini = faux
    tant que pas fini
        lire un caractère : c
        suivant la valeur de c
            retour chariot : fini = vrai
            'l' : mouvement droite
            'j' : mouvement gauche
            ...
    Dernière remarque : tu vas forcément, à un moment, vouloir avoir un affichage un peu plus subtil que des caractères ASCII dans une console. Les bibliothèques graphiques intègrent toujours une façon de lire le clavier, avec les constantes qui vont bien pour les touches spéciales.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

Discussions similaires

  1. [PROJET] communication entre serveur minecraft et Arduino
    Par invite946bb077 dans le forum Logiciel - Software - Open Source
    Réponses: 4
    Dernier message: 07/07/2012, 08h06
  2. Minecraft Compact 6720S
    Par invite9613952b dans le forum Logiciel - Software - Open Source
    Réponses: 0
    Dernier message: 20/03/2012, 16h59
  3. HELP "Unable to access jarfile" minecraft
    Par invite4e49250f dans le forum Logiciel - Software - Open Source
    Réponses: 4
    Dernier message: 02/08/2011, 16h39