pacman en C

pacman en C - C - Programmation

Marsh Posté le 15-04-2012 à 16:36:52    

kelk1 peut m'aider a programmer pacman en C a l'aide de la bibliothéque SDL??

Reply

Marsh Posté le 15-04-2012 à 16:36:52   

Reply

Marsh Posté le 16-04-2012 à 22:12:50    

Oui, commence et on t'aidera :)


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 02-05-2012 à 05:34:51    

Je suis également entrain de réaliser un pacman en C avec la bibliothèque SDL, plus j'avance plus je me rends compte qu'il est impératif de bien ranger et d'ordonner son code  :cry:  
Aujourd'hui j'hésite à tout recommencer car je ne parviens pas à placer mon code dans des fonctions...
 

Code :
  1. // fichier jeu.c  (main.c contient un menu vers le jeu et un éditeur de niveau)
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <SDL/SDL.h>
  5. #include <SDL_image.h>
  6. #include <SDL_ttf.h>
  7. #include "constantes.h"  // taille du niveau + directions + éléments
  8. #include "jeu.h"
  9. void jouer(SDL_Surface* ecran)
  10. {
  11.     SDL_Surface *pacman[4] = {NULL}; // 4 surfaces pour chacune des directions de pacman
  12.     SDL_Surface *ennemi[4] = {NULL};
  13.     SDL_Surface *mur = NULL, *bonus = NULL, *graine = NULL, *pacmanActuel = NULL, *ennemiActuel = NULL;
  14.     SDL_Surface *texte = NULL;
  15.     SDL_Rect position, positionJoueur, positionEnnemi;
  16.     SDL_Event event;
  17.     // police à utiliser plus tard
  18. TTF_Init();
  19. TTF_Font *police = NULL;
  20. SDL_Color couleurRouge = {170, 0, 0};
  21. police = TTF_OpenFont("pacfont.ttf", 20); // Ouverture de la police au début
  22. texte = TTF_RenderText_Blended(police, "score : ", couleurRouge);
  23.     int continuer = 1, objectifsRestants = 0, i = 0, j = 0;
  24.     int carte[NB_BLOCS_LARGEUR][NB_BLOCS_HAUTEUR] = {0};
  25.     int score=0;
  26.     char tableauScore[40]="";
  27.     // Chargement des sprites (décors, personnage...)
  28.     mur = IMG_Load("img/mur.png" );
  29.     graine = IMG_Load("img/graine.png" );
  30.     bonus = IMG_Load("img/bonus.png" );
  31.     ennemi[HAUT] = IMG_Load("img/ennemiUp.png" );
  32.     ennemi[BAS] = IMG_Load("img/ennemiDown.png" );
  33.     ennemi[GAUCHE] = IMG_Load("img/ennemiLeft.png" );
  34.     ennemi[DROITE] = IMG_Load("img/ennemiRight.png" );
  35.     pacman[BAS] = IMG_Load("img/pacmanDown.png" );
  36.     pacman[GAUCHE] = IMG_Load("img/pacmanLeft.png" );
  37.     pacman[HAUT] = IMG_Load("img/pacmanUp.png" );
  38.     pacman[DROITE] = IMG_Load("img/pacmanRight.png" );
  39.     pacmanActuel = pacman[DROITE];
  40.     ennemiActuel = ennemi[BAS];
  41.     // Chargement du niveau
  42.     if (!chargerNiveau(carte))
  43.         exit(EXIT_FAILURE);
  44.     // Recherche de la position de pacman et ennemi au départ
  45.     for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  46.     {
  47.         for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  48.         {
  49.             if (carte[i][j] == PACMAN) // Si pacman se trouve à cette position sur la carte
  50.             {
  51.                 positionJoueur.x = i;
  52.                 positionJoueur.y = j; // on enregistre les coordoonées
  53.                 carte[i][j] = VIDE;
  54.             }
  55.             else if (carte[i][j] == ENNEMI) // Si l'ennemi se trouve à cette position sur la carte
  56.             {
  57.                 positionEnnemi.x = i;
  58.                 positionEnnemi.y = j;
  59.                 carte[i][j] = VIDE;
  60.             }}}
  61.     // Activation de la répétition des touches
  62.     SDL_EnableKeyRepeat(100, 100);
  63.     while (continuer)
  64.     {
  65.         SDL_PollEvent(&event);
  66.         SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));  // Effacement de l'écran
  67.            // Placement des objets à l'écran
  68.         objectifsRestants = 0;
  69.         for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  70.         {
  71.             for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  72.             {
  73.                 position.x = i * TAILLE_BLOC;
  74.                 position.y = j * TAILLE_BLOC;
  75.                 switch(carte[i][j])
  76.                 {
  77.                     case MUR:
  78.                         SDL_BlitSurface(mur, NULL, ecran, &position);
  79.                         break;
  80.                     case GRAINE:
  81.                         SDL_BlitSurface(graine, NULL, ecran, &position);
  82.                       objectifsRestants = 1;
  83.                         break;
  84.                     case ENNEMI:
  85.                         SDL_BlitSurface(ennemi, NULL, ecran, &position);
  86.                         break;
  87.                     case BONUS:
  88.                         SDL_BlitSurface(bonus, NULL, ecran, &position);
  89.                         break;
  90.                     case PACMAN:
  91.                         SDL_BlitSurface(pacman, NULL, ecran, &position);
  92.                         break;        }}}
  93.             switch(event.type)
  94.             {
  95.                     case SDL_QUIT:
  96.                     continuer = 0;
  97.                     break;
  98.                     case SDL_KEYDOWN:
  99.                     switch(event.key.keysym.sym)
  100.                             {
  101.                                 case SDLK_ESCAPE:
  102.                                     continuer = 0;
  103.                                     break;
  104.                                 case SDLK_UP:
  105.                                     pacmanActuel = pacman[HAUT];
  106.                                     deplacerJoueur(carte, &positionJoueur, HAUT);
  107.                                     break;
  108.                                 case SDLK_DOWN:
  109.                                     pacmanActuel = pacman[BAS];
  110.                                     deplacerJoueur(carte, &positionJoueur, BAS);
  111.                                     break;
  112.                                 case SDLK_RIGHT:
  113.                                     pacmanActuel = pacman[DROITE];
  114.                                     deplacerJoueur(carte, &positionJoueur, DROITE);
  115.                                     break;
  116.                                 case SDLK_LEFT:
  117.                                     pacmanActuel = pacman[GAUCHE];
  118.                                     deplacerJoueur(carte, &positionJoueur, GAUCHE);
  119.                                     break;
  120.                             }
  121.             break;
  122.             }
  123.           if (!objectifsRestants)
  124.             continuer = 0;
  125.         // On place le joueur à la bonne position
  126.         position.x = positionJoueur.x * TAILLE_BLOC;
  127.         position.y = positionJoueur.y * TAILLE_BLOC;
  128.         SDL_BlitSurface(pacmanActuel, NULL, ecran, &position);
  129.         position.x = positionEnnemi.x * TAILLE_BLOC;
  130.         position.y = positionEnnemi.y * TAILLE_BLOC;
  131.         SDL_BlitSurface(ennemiActuel, NULL, ecran, &position);
  132.         SDL_Flip(ecran);
  133.         SDL_Delay(75);
  134.     }
  135.     // Désactivation de la répétition des touches (remise à 0)
  136.     SDL_EnableKeyRepeat(0, 0);
  137.     // Libération des surfaces chargées
  138.     SDL_FreeSurface(mur);
  139.     SDL_FreeSurface(bonus);
  140.     SDL_FreeSurface(graine);
  141.     for (i = 0 ; i < 4 ; i++)
  142.     {
  143.         SDL_FreeSurface(pacman[i]);
  144.         SDL_FreeSurface(ennemi[i]);
  145.     }
  146. }
  147. void deplacerJoueur(int carte[][NB_BLOCS_HAUTEUR], SDL_Rect *pos, int direction)
  148. {
  149.     switch(direction)
  150.     {
  151.         case HAUT:
  152.             if ((pos->y - 1 < 0)||(carte[pos->x][pos->y - 1] == MUR)) // S'il y a un mur, on arrête
  153.                 break;
  154.             mangerObjet(&carte[pos->x][pos->y], &carte[pos->x][pos->y-1]);
  155.             pos->y--;
  156.             break;
  157.         case BAS:
  158.             if ((pos->y + 1 >= NB_BLOCS_HAUTEUR)||(carte[pos->x][pos->y + 1] == MUR))
  159.             break;
  160.             else
  161.             mangerObjet(&carte[pos->x][pos->y], &carte[pos->x][pos->y+1]);
  162.             pos->y++;
  163.             break;
  164.         case GAUCHE:
  165.             if ((pos->x - 1 < 0)||(carte[pos->x - 1][pos->y] == MUR))
  166.             break;
  167.             else
  168.             mangerObjet(&carte[pos->x][pos->y], &carte[pos->x-1][pos->y]);
  169.             pos->x--;
  170.             break;
  171.         case DROITE:
  172.             if ((pos->x + 1 >= NB_BLOCS_LARGEUR)||(carte[pos->x + 1][pos->y] == MUR))
  173.                 break;
  174.             else
  175.             mangerObjet(&carte[pos->x][pos->y], &carte[pos->x+1][pos->y]);
  176.             pos->x++;
  177.             break;
  178.     }
  179. }
  180. int mangerObjet(int *premiereCase, int *secondeCase)
  181. {
  182. if (*premiereCase == VIDE)
  183.     {
  184.         if (*secondeCase == GRAINE)
  185.         {
  186.             *secondeCase = VIDE;
  187.         }
  188.         if (*secondeCase == BONUS)
  189.             *secondeCase = VIDE;
  190. }
  191. }


Je manque clairement de repère et de méthodologie notamment pour la boucle "while" du jeu et le placement  du décor ... faut-il créer une structure pour chaque entité du jeu ?
- SDL_BlitSurface
- Pacman
- Ennemi
- Sprites
...

Reply

Marsh Posté le 02-05-2012 à 12:08:34    

Personnellement, je conçois pas tellement de programmer un jeu sans POO, c'est beaucoup plus simple avec des classes, mais tu peux toujours émuler ça, il te faudrait du coups une structure pour pacman qui contiendrait sa position x/y/image du sprite à afficher, idem pour les fantômes, ensuite tu fais des fonctions du style 'pacman_tick' qui prend un pointeur sur une structure pacman, qui déplacerait celui-ci selon les touches pressés. Pour la carte, une structure aussi jdirais, où y'aurait la largeur/la hauteur et un tableau en 2D pour les tiles placés dessus, et une liste chainée pour la liste des objets (ennemis/objets à ramasser). Ensuite, soit tu fais une instance en global (déclaré hors d'une fonction) soit tu fais passer sur les fonctions tick de pacman/ennemis

 

edit : Roh lala, la phrase super longue sans point :o

Message cité 1 fois
Message édité par Terminapor le 02-05-2012 à 12:09:05

---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 03-05-2012 à 19:44:08    

Pour bien comprendre le fonctionnement de la chose je souhaite procéder step by step en commençant par initialiser une structure générale dans mes constantes :

Code :
  1. struct partie
  2. {
  3. SDL_Surface * ecran;
  4. int score;
  5. };
  6. typedef struct partie Partie;


 
Maintenant si je souhaite (dans le code que j'ai posté tout en haut) utiliser ma structure en argument pour la fonction jouer()
- par quoi remplacer (SDL_Surface* ecran) ?
- par quoi remplacer "ecran" ?

Reply

Marsh Posté le 03-05-2012 à 19:56:17    

Par rien, le prototype de jouer sera différent :

Code :
  1. void jouer(partie * part)
  2. {
  3. }
 

Bon, je pense que ta structure "partie" manque d'informations (une liste d'objets pour les ennemies, un pointeur pour le joueur et compagnie)


Message édité par Terminapor le 03-05-2012 à 19:56:28

---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 03-05-2012 à 20:33:59    

Très bien, alors pour commencer j'alloue de la mémoire à ma structure dans mon main.c :

Code :
  1. Partie *jeu = NULL;
  2. jeu = (Partie *)malloc(sizeof(Partie));


 
Puis je change le prototype dans mon header et dans le fichier.c :

Code :
  1. void jouer(SDL_Surface* ecran, Partie* jeu)


Miracle le jeu se lance correctement

Reply

Marsh Posté le 04-05-2012 à 02:48:33    

Voui mais pas besoin de faire une allocation mémoire, tu peux faire comme ça :
 
Partie jeu;
 
jouer(ecran,&jeu);
 
le '&' utilisé avant un nom de variable permet de récupérer l'adresse mémoire de celle-ci


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 04-05-2012 à 20:19:11    

Tu veux dire que par cette méthode l'allocation sera automatique et ceci peu importe la taille et les différents paramètres de la structure ?

Reply

Marsh Posté le 04-05-2012 à 22:23:10    

Terminapor a écrit :

Personnellement, je conçois pas tellement de programmer un jeu sans POO


Même pour le fun et le challenge ? Regarde en quoi est programmé Prince of Persia.


---------------
Des Bisous et des nounours ! | Internet 2025 | Dungeon-Generator
Reply

Marsh Posté le 04-05-2012 à 22:23:10   

Reply

Marsh Posté le 05-05-2012 à 01:50:46    

Voui mais pas pour un projet sérieux, c'pour ça que je me tue à implémenter de la pseudo POO en lua :D

 
caps lock a écrit :

Tu veux dire que par cette méthode l'allocation sera automatique et ceci peu importe la taille et les différents paramètres de la structure ?


Ben c'est juste qu'au lieu de faire une allocation mémoire via malloc() et de faire passer le pointeur (donc l'adresse vers la nouvelle variable), tu fais directement passer une variable alloué qui sera automatiquement supprimé au moment où le bloc d'instructions est fini


Message édité par Terminapor le 05-05-2012 à 01:52:10

---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 05-05-2012 à 02:37:14    

Oui, enfin, à partir du moment ou il a besoin de faire du malloc dans sa struct, ça n'a pas une grande importance, et à la limite, mieux vaut un 'constructeur' et un 'destructeur' uniques qui font tout le boulot.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 05-05-2012 à 22:07:58    

Je ne me suis pas encore occupé de toute la partie gestion des fantômes et pourtant lorsque j'exécute le jeu je constate via le gestionnaire des tâches de windows que le jeu prend 100ko de mémoire par seconde, comment je dépanne ça ? (avant de poster mon code ici)

Reply

Marsh Posté le 05-05-2012 à 22:18:22    

J'ai détecté que l'erreur provenait de la gestion des scores :

Code :
  1. TTF_Init();
  2. TTF_Font *police = NULL;
  3. SDL_Color couleurRouge = {170, 0, 0};
  4. police = TTF_OpenFont("tahoma.ttf", 20); // Chargement de la police
  5. char tableauScore[40]="";                     // tableau qui servira à stocker le score
  6. jeu->score=0;
  7. sprintf(tableauScore, "Score : %d", jeu->score);
  8. texte = TTF_RenderText_Blended(police, tableauScore, couleurRouge);
  9.         //actualisation du score dans la boucle while du jeu
  10.         sprintf(tableauScore, "Score : %d", jeu->score);
  11.         texte = TTF_RenderText_Blended(police, tableauScore, couleurRouge);
  12.         position.x = 60;
  13.         position.y = 670;
  14.         SDL_BlitSurface (texte, NULL, jeu->ecran, &position);
  15.  
  16. // a la fin du jeu je ferme la gestion des polices
  17.     TTF_CloseFont(police);
  18.     TTF_Quit();


Reply

Marsh Posté le 07-05-2012 à 06:20:24    

Code :
  1. texte = TTF_RenderText_Blended(police, tableauScore, couleurRouge);


Je viens de comprendre qu'actualiser le score en permanence était inutile, j'ai coupé cette ligne et je l'ai rajouté à la suite de chaque déplacement de mon pacman. Du coup maintenant la consommation de la RAM monte "manuellement" dès que je bouge le programme prend +4Ko :lol:

 

EDIT : problème trouvé
- Je pensais que c'était un problème d'allocation de la mémoire avec tableauScore, même après un malloc le problème persistait
- il me manquait un SDL_FreeSurface(texte) avant de remodifier "texte" dans la boucle


Message édité par caps lock le 07-05-2012 à 06:47:50
Reply

Marsh Posté le 07-05-2012 à 09:50:51    

Tout ça est dans la doc en ligne de SDL, hein...
google TTF_RenderText_Blended -> http://www.libsdl.org/projects/doc [...] tf_44.html ou on lit:

Code :
  1. // Render some text in blended black to a new surface
  2. // then blit to the upper left of the screen
  3. // then free the text surface
  4. //SDL_Surface *screen;
  5. SDL_Color color={0,0,0};
  6. SDL_Surface *text_surface;
  7. if(!(text_surface=TTF_RenderText_Blended(font,"Hello World!",color))) {
  8.     //handle error here, perhaps print TTF_GetError at least
  9. } else {
  10.     SDL_BlitSurface(text_surface,NULL,screen,NULL);
  11.     //perhaps we can reuse it, but I assume not for simplicity.
  12.     SDL_FreeSurface(text_surface);
  13. }


A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 09-05-2012 à 00:16:55    

Mes amis,
J'ai voulu m'amuser un peu et j'ai dôté d'une bombe mon cher petit pacman.
Je parviens à lui faire poser une bombe et à la faire exploser.
 
Chaque bloc dans mon jeu fais 25x25 pixel.
 
La bombe casse tous les murs dans les environs comme selon l'exemple suivant :
                X represente un mur
                - un chemin
                O la bombe
XXX
-O-
XXX
 
La bombe détruit donc les éléments en diagonale à la différence d'un bomberman classic.
Mon problème c'est que j'ai utilisé pour l'explosion une série d'image qui sont volontairement plus grandes que la taille d'un bloc pour faire quelque chose de réaliste, l'animation est réalisée en 75x75 sauf que vous l'aurez normalement déjà compris l'action démarre à l'emplacement de la bombe et le coin haut/gauche de l'animation vient se blitter en remplacement de l'image de la bombe. Ce qui provoque un gros et affreux décalage de l'image.
http://hfr-rehost.net/self/pic/288ce4f784ec2193265f9c308131a0dcf42dcfa1.png
http://hfr-rehost.net/self/pic/a148e980702790f85093c68852b1ad1e891dd956.png
 

Reply

Marsh Posté le 09-05-2012 à 02:02:46    

Si tu savais les horreurs du codage de certains jeux parfois... http://www.dodgycoder.net/2012/02/ [...] opers.html
 
Mon favori est celui la:

Citation :

My favorite trick has been from "Jak and Daxter" - "trip and fall" - e.g. if the streaming falls behind, make the character trip and fall, thus giving time for the streamer to catch up.

[:rofl]  [:rofl]  [:rofl]  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 09-05-2012 à 03:29:14    

Its not a bug, its a feature! - Philip Tan

:pt1cable:  :lol:

Reply

Marsh Posté le 09-05-2012 à 07:43:56    

En ce qui concerne le déplacement des ennemis, je parviens à en faire bouger un en effectuant un random sur les 4 positions possibles (haut,bas,droite,gauche), outre le fait qu'il ne semble même pas atteindre le QI d'une mouche coincée derrière une fenêtre, je me rends rapidement compte que créer une intelligence artificielle ne sera pas une mince affaire.  
 
- Dans un switch est-il possible de "sauter" le break pour tester une autre possibilité si l'une d'elle échoue ?
Si on prend l'exemple du code suivant, si un mur se trouve au dessus du personnage et que le random choisi la direction HAUT, le personnage n'avancera pas et on sortira du switch...

Code :
  1. int deplacerEnnemi(int carte[][NB_BLOCS_HAUTEUR], SDL_Rect *ennemi, int direction, Sprites *images)
  2. {
  3.     switch(direction)
  4.     {
  5.         case HAUT:
  6.             images->ennemiActuel = images->ennemi[HAUT];
  7.             if ((ennemi->y - 1 < 0)||(carte[ennemi->x][ennemi->y - 1] == MUR)||(carte[ennemi->x][ennemi->y - 1] == BOMBE))
  8.             break;
  9.             ennemi->y--;
  10.             break;
  11.         case BAS:
  12. ...etc...


 
Deuxième question, je commence à m'intéresser à l'algorithme A* mais est-il implémentable avec le langage C ? car pour le moment je ne trouve que des tutoriels pour le C++
 :hello:

Reply

Marsh Posté le 09-05-2012 à 10:09:22    

Citation :

Dans un switch est-il possible de "sauter" le break pour tester une autre possibilité si l'une d'elle échoue ?


Tu peux faire  
flag = false;
do  {
      direction = random(...);
      switch (direction) {
      ...
      }
} while (!flag);
ou flag est positionné quand tu as effectivement un mouvement.
Mais dans ton cas, il faudrait que la direction soit re-calculée entre le do et le switch, et non pas comme paramètre de la fonction.
Sinon, il te faudra boucler sur l'appel de deplacerEnnemi.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 09-05-2012 à 20:24:19    

Lorsque j'écris ce code le personnage ne va en plus haut et je ne parviens pas à comprendre pourquoi

Code :
  1. int deplacerEnnemi(int carte[][NB_BLOCS_HAUTEUR], SDL_Rect *ennemi, int direction, Sprites *images)
  2. {
  3.     switch(direction)
  4.     {
  5.         case HAUT:
  6.             if ((ennemi->y - 1 < 0)||(carte[ennemi->x][ennemi->y - 1] == MUR)||(carte[ennemi->x][ennemi->y - 1] == BOMBE))
  7.             direction=(rand() % 4);   //  <---------- nouvelle ligne
  8.             break;
  9.             images->ennemiActuel = images->ennemi[HAUT];
  10.             ennemi->y--;
  11.             break;
  12.         case BAS:

Reply

Marsh Posté le 09-05-2012 à 22:55:59    

if ((ennemi->y - 1 < 0)||(carte[ennemi->x][ennemi->y - 1] == MUR)||(carte[ennemi->x][ennemi->y - 1] == BOMBE)) {
            direction=(rand() % 4);   //  <---------- nouvelle ligne
            break;
        }
            images->ennemiActuel = images->ennemi[HAUT];
            ennemi->y--;
            break;
        case BAS:
 
non?
Voila pourquoi certains dont je fais partie mettent presque toujours des accolades pour un if, quand bien même il ne fait qu'une ligne.
A+,

Message cité 1 fois
Message édité par gilou le 09-05-2012 à 22:57:56

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 09-05-2012 à 23:32:30    

Effectivement! merci

Reply

Marsh Posté le 12-05-2012 à 03:38:54    

J'ai créé une fonction RandomEnnemi comme son nom l'indique qui déplace un ennemi aléatoirement. Cette fonction est placée dans la boucle while() et est "timé" pour être effectué une fois toute les 150ms.
 
J'essaie donc de créer un semblant d'intelligence en faisant parcourir aléatoirement la carte à mon ennemi, à chaque fois qu'il rencontrera un mur ou quelque chose qui indiquera qu'il ne peut pas passer les coordonnées seront inscrites dans le fichier "test.txt"
 

Code :
  1. int RandomEnnemi(int carte[][NB_BLOCS_HAUTEUR], SDL_Rect *ennemi, int direction, Sprites *images)
  2. {
  3. FILE* fichier = NULL;
  4.     fichier = fopen("test.txt", "a+" );  // création du fichier qui va stocker les coordonnées
  5.     switch(direction)
  6.     {
  7.         case HAUT:
  8.             if ((ennemi->y - 1 < 0)||(carte[ennemi->x][ennemi->y - 1] == MUR)||(carte[ennemi->x][ennemi->y - 1] == MURB)||(carte[ennemi->x][ennemi->y - 1] == BOMBE))  // si le mouvement est impossible
  9.             {
  10.             fprintf(fichier,"%d %d ", ennemi->x, ennemi->y-1);   // inscription des coordonnées dans le fichier
  11.             do{direction=(rand() % 4); }while((direction!=0)&&(direction!=1)); // cette ligne a pour but de forcer un mouvement supplémentaire car si l'ennemi rencontre un mur il ne bougera pas --> je demande donc un random des 4 directions possible et j'interdis de reprendre la même direction et la direction opposée
  12.             break;   // on sort du switch
  13.             }
  14.             images->ennemiActuel = images->ennemi[HAUT];  // la direction est possible donc je change l'image de l'ennemi pour plus de réalisme
  15.             ennemi->y--; // je fais bouger l'ennemi
  16.             break;
  17.         case BAS:
  18.             if ((ennemi->y + 1 >= NB_BLOCS_HAUTEUR)||(carte[ennemi->x][ennemi->y + 1] == MUR)||(carte[ennemi->x][ennemi->y + 1] == MURB)||(carte[ennemi->x][ennemi->y + 1] == BOMBE))
  19. {
  20.             fprintf(fichier,"%d %d ", ennemi->x, ennemi->y+1);
  21.             do{direction=(rand() % 4); }while((direction!=1)&&(direction!=0));
  22.             break;
  23.             }
  24.              images->ennemiActuel = images->ennemi[BAS];
  25.             ennemi->y++;
  26.             break;
  27.         case GAUCHE:  //  GAUCHE et DROITE sont codés par la même logique de haut et bas
  28.       break;
  29.         case DROITE:
  30.             break;
  31.     }
  32.     fclose(fichier);  // je n'oublie pas de fermer le fichier
  33.     return direction;   // je retourne la direction prise (je ne m'en sers pas pour le moment)
  34. }


 
Maintenant que j'ai créé un fichier qui actualise en temps réel les mouvements impossible de l'ennemi je n'arrive pas du tout à l'exploiter... J'ai imaginé à un moment créer une sorte de boucle de la fonction ci-dessus en mettant le fichier en paramètre.
Voici ce que je veux faire et mettre dans la boucle principale :

Code :
  1. DO
  2. {
  3. RandomEnnemi(carte, &positionEnnemi, (rand() % 4), images);
  4. } WHILE( !  (je veux mettre ici les coordonnées récupérées par le fichier)  );


 
Je suis bloqué là-dessus depuis un moment car :
- je ne parviens pas à exploiter les données de mon fichier
- je trouve le fichier mal conçu car les "mauvaises coordonnées" sont présentes de nombreuses fois dans le fichier, pour bien faire il faudrait empêcher la répétition des mouvements dans le switch
 
 
 
 

Reply

Marsh Posté le 14-05-2012 à 07:42:29    

Nouveau problème!
Je me sers d'un éditeur de niveau pour modifier ma carte de jeu et également d'une énumération pour chaque élément du décor :
0 MUR
1 PACMAN
2 BONUS  etc
10 PORTE
La liste est maintenant supérieur à 9 et donc le code suivant n'est plus compatible  :sweat:  :

Code :
  1. int chargerNiveau(int niveau[][NB_BLOCS_HAUTEUR])      //hauteur=largeur=28
  2. {
  3.     FILE* fichier = NULL;
  4.     char ligneFichier[NB_BLOCS_LARGEUR * NB_BLOCS_HAUTEUR + 1] = {0};
  5.     int i = 0, j = 0;
  6.     fichier = fopen("niveaux.lvl", "r" );    // ouverture du fichier contenant la carte
  7.     if (fichier == NULL)
  8.         return 0;
  9.     fgets(ligneFichier, NB_BLOCS_LARGEUR * NB_BLOCS_HAUTEUR + 1, fichier);  // +1 pour le caractère de fin de ligne
  10.     for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  11.     {
  12.         for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  13.         {
  14.             switch (ligneFichier[(i * NB_BLOCS_LARGEUR) + j])
  15.             {
  16.                 case '0':
  17.                     niveau[j][i] = 0;
  18.                     break;
  19.                 case '1':
  20.                     niveau[j][i] = 1;
  21.                     break;
  22.                 case '2':
  23.                     niveau[j][i] = 2;
  24.                     break;
  25.                 case '3':
  26.                     niveau[j][i] = 3;
  27.                     break;
  28.                 case '4':
  29.                     niveau[j][i] = 4;
  30.                     break;
  31.                 case '5':
  32.                     niveau[j][i] = 5;
  33.                     break;
  34.                 case '6':
  35.                     niveau[j][i] = 6;
  36.                     break;
  37.                 case '7':
  38.                     niveau[j][i] = 7;
  39.                     break;
  40.                 case '8':
  41.                     niveau[j][i] = 8;
  42.                     break;
  43.                 case '9':
  44.                     niveau[j][i] = 9;
  45.                     break;
  46.                 case '10':
  47.                     niveau[j][i] = 10;
  48.                     break;
  49.                 case '11':
  50.                     niveau[j][i] = 11;
  51.                     break;
  52.                 case '12':
  53.                     niveau[j][i] = 12;
  54.                     break;
  55.             }
  56.         }
  57.     }
  58.     fclose(fichier);
  59.     return 1;
  60. }
  61. int sauvegarderNiveau(int niveau[][NB_BLOCS_HAUTEUR])
  62. {
  63.     FILE* fichier = NULL;
  64.     int i = 0, j = 0;
  65.     fichier = fopen("niveaux.lvl", "w" );
  66.     if (fichier == NULL)
  67.         return 0;
  68.     for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  69.     {
  70.         for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  71.         {
  72.             fprintf(fichier, "%d", niveau[j][i]);
  73.         }
  74.     }
  75.     fclose(fichier);
  76.     return 1;
  77. }


Pour faire simple, la valeur 10 qui doit représenter une porte est comprise comme un 1 et un 0 (PACMAN + MUR)

 

Si je modifie le "fprintf(fichier, "%d ", niveau[j][i])" en rajoutant un espace après le %d je ne parviens pas à inclure cet espace dans la formule de fgets().
Dans le pire des cas je pense régler cette histoire en forçant un saut de ligne après chaque valeur mais ça ne m'arrange vraiment pas!
Si quelqu'un a une idée :)

 

EDIT : en remplaçant %d par %x ça semble fonctionner :o


Message édité par caps lock le 14-05-2012 à 08:00:41
Reply

Marsh Posté le 14-05-2012 à 12:19:34    

Quand tu sauvegardes valeur par valeur (ici avec un blanc entre chaque valeur et un saut de ligne après chaque ligne)

Code :
  1. int sauvegarderNiveau(int niveau[][NB_BLOCS_HAUTEUR])
  2. {
  3.     FILE* fichier = NULL;
  4.     int i = 0, j = 0;
  5.     fichier = fopen("niveaux.lvl", "w" );
  6.     if (fichier == NULL)
  7.         return 0;
  8.     for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  9.     {
  10.         for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  11.         {
  12.             fprintf(fichier, "%d ", niveau[j][i]);
  13.         }
  14.         fprintf(fichier, "\n" ); // plus propre pour relire, mais le code marchera sans
  15.     }
  16.     fclose(fichier);
  17.     return 1;
  18. }


Tu lis valeur par valeur:

Code :
  1. int chargerNiveau(int niveau[][NB_BLOCS_HAUTEUR])      //hauteur=largeur=28
  2. {
  3.     FILE* fichier = NULL;
  4.     int i = 0, j = 0;
  5.     int niveau;
  6.     fichier = fopen("niveaux.lvl", "r" );    // ouverture du fichier contenant la carte
  7.     if (fichier == NULL)
  8.         return 0;
  9.     for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  10.     {
  11.         for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  12.         {
  13.             fscanf(fichier, "%d ", &niveau); // TODO: tester le retour et sortir en erreur s'il y a lieu
  14.             switch (niveau)
  15.             {
  16.                 case '0':
  17.                     niveau[j][i] = 0;
  18.                     break;
  19.                 case '1':
  20.                     niveau[j][i] = 1;
  21.                     break;
  22.                 case '2':
  23.                     niveau[j][i] = 2;
  24.                     break;
  25.                 case '3':
  26.                     niveau[j][i] = 3;
  27.                     break;
  28.                 case '4':
  29.                     niveau[j][i] = 4;
  30.                     break;
  31.                 case '5':
  32.                     niveau[j][i] = 5;
  33.                     break;
  34.                 case '6':
  35.                     niveau[j][i] = 6;
  36.                     break;
  37.                 case '7':
  38.                     niveau[j][i] = 7;
  39.                     break;
  40.                 case '8':
  41.                     niveau[j][i] = 8;
  42.                     break;
  43.                 case '9':
  44.                     niveau[j][i] = 9;
  45.                     break;
  46.                 case '10':
  47.                     niveau[j][i] = 10;
  48.                     break;
  49.                 case '11':
  50.                     niveau[j][i] = 11;
  51.                     break;
  52.                 case '12':
  53.                     niveau[j][i] = 12;
  54.                     break;
  55.             }
  56.         }
  57.     }
  58.     fclose(fichier);
  59.     return 1;
  60. }


Bon, j'ai pas testé le code, mais tu vois l'idée.
Comme de toute façon, la lecture de ton fichier est bufferisée, c'est pas vraiment beaucoup plus coûteux qu'une lecture unique avec fgets.
 
A+,


Message édité par gilou le 14-05-2012 à 12:21:12

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 25-06-2012 à 07:28:44    

gilou a écrit :


Voila pourquoi certains dont je fais partie mettent presque toujours des accolades pour un if, quand bien même il ne fait qu'une ligne.
A+,


C'est plus simple à lire je suppose.


---------------
Des Bisous et des nounours ! | Internet 2025 | Dungeon-Generator
Reply

Marsh Posté le 25-06-2012 à 10:21:23    

C'est surtout plus simple à maintenir:
Pas de risque d'erreur si on rajoute des lignes, pas de pb de dangling if, etc.
Et comme j'écris aussi pas mal de perl, langage dans lequel les parenthèses sont obligatoires pour une instruction après un if (mais pas une avant il me semble :pt1cable: ), ça évite de se poser des questions.
Et comme le compilo va générer le même code...
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 10-04-2013 à 18:06:44    

slt tt le monde :), moi aussi, je suis entrain de faire un jeu de pacman à l'aide de SDL, mais le probleme que le deplacement de pacman ou des enemies n'est pas fluide, il fait un saut d'une case chaque deplacement :'(, comment faire pour rendre pacman et les ennemies se bougent d'un pixel!!

Reply

Marsh Posté le 11-04-2013 à 01:06:58    

En déplaçant d'un pixel ? :D


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed