affichage, sauvegarde etc.. d'une map 2D

affichage, sauvegarde etc.. d'une map 2D - C++ - Programmation

Marsh Posté le 20-04-2006 à 16:53:01    

Bonjour tout le monde
 
J'ai un petit projet qui est la crétion d'un jeux 2D (genre zelda) sans prétention, ceci sera ma première expérience de jeux video (générallement je code plus de petites appli. "utile" qui ne touche en aucun cas au domaine du jeux video).
Donc après avoir choisi la SDL pour faire ce jeux (qui je pense est une bonne bibliothéque), je décide de me lancer dans le cahier des charge, et là j'ai trop du mal à visualiser un algorithme pour gérer l'affichage la crétion de la map etc...
 
Donc voilà :
je compte représenter la map dans un tableau a 2 dimensions, charger mon chipset (qui contient tout les tiles ) dans un SD_Surface *chipset
la map sera lu a partir d'un fichier qui contiendra des chiffres qui représenterons les tiles (un editeur de map verra donc le jour)
une fois le fichier de la map chargé je parcourerais mon chipset en fonction du chiffre (mais là je vois pas comment, comment faire le liens entre le chiffre et la position de la tile a afficher)
...
 
enfin bref comme vous pouvez le voir j'ai un gros problème de conceptualisation, je n'arrive pas a visualiser l'affichage de la map ainsi que la sauvegarde etc...
 
ce que j'attend de vous ce sont des conseils, des methodes, un algorithme ?! me dire si je suis sur la bonne voix et peut-etre m'éclairer sur "comment faire le liens entre le chiffre et la position de la tile a afficher" etc...


Message édité par blastman le 20-04-2006 à 17:20:50

---------------
http://www.blastmanu.info
Reply

Marsh Posté le 20-04-2006 à 16:53:01   

Reply

Marsh Posté le 20-04-2006 à 16:56:20    

Crée un objet plus complexe CTile qui contiendrait, en plus de son identifiant de représentation ses coordonnées.


Message édité par _darkalt3_ le 20-04-2006 à 17:01:27
Reply

Marsh Posté le 20-04-2006 à 17:11:18    

je devrais donc faire une procédure chargementTile qui se chargerai avant toute manipulation de parcourir le chipset et d'attribuer pour chaque tile un identifiant et sa position en x et y (l'objet CTile), et ensuite si je veux charger une map j'aurai simplement à lire dans le fichier .map (par exemple) l'identifiant et ensuite en fonction de celui-ci je parcours mon chipset et j'affiche, c'est ca ?


Message édité par blastman le 20-04-2006 à 17:12:28

---------------
http://www.blastmanu.info
Reply

Marsh Posté le 20-04-2006 à 17:12:34    

par exemple, en gérant le tout dans un vector.

Reply

Marsh Posté le 20-04-2006 à 17:16:13    

hmm, ok bon j'vais déjà essayer de voir ca, merci :)
 
si quelqu'un à une méthode pour gérer une map je suis prenneur


---------------
http://www.blastmanu.info
Reply

Marsh Posté le 21-04-2006 à 01:44:42    

hum, si c'est une carte 2D, divisée en carrés, chaque carré contenant une tile, tu peut t'inspirer du format d'image XPM, avec des tiles au lieu de couleurs. Ça ressemble à ça:

  • entête: tailleX tailleY nombre_tiles_utilisés
  • liste des fichiers tiles utilisés séparés par \n:

sol.bmp
sable.bmp
mer.bmp
...

  • carte, format binaire, par ex. une plage:

00000
01110
11211
22222
22222
(note: 0=sol, 1=sable, 2=mer)
 
Quand tu lis la carte, tu crée deux tableaux:

  • les tiles: nom fichier et image SDL
  • la carte: numéro de tile dans le tableau de tiles


Quand tu édite la carte, tu ajoute des tiles à la liste des tiles utilisés, tu modifie la taille de la carte, et/ou tu change les numéros de tiles dans chaque case du tableau 2D.
 
Quand tu sauvegarde la carte, tu sauvegarde l'entête, puis le tableau de tiles utilisés en utisant le nom de fichier tile, puis la carte 2D.
 
Quand tu affiche la carte, tu affiche une partie du tableau 2D, pour chaque case affichée le tile est dans tiles_utilisés[ carte[x][y] ]. Quand tu scrolle la carte, tu scrolle l'écran, et tu ne réaffiche que les nouveaux tiles qui apparaissent sur les bords.
 
SDL possède des fonctions pour charger différents formats de fichiers image.
 
Si tu souhaite ajouter plusieurs niveaux de hauteur tu peut utiliser le même principe avec un tableau 3D pour la carte.
 
Si tu souhaite ajouter des objets par dessus la carte, comme des personnages, tu peut t'inspirer de formats tels que HTML ou XML:
<JOUEUR>
  <POSX>10</POSX>
  <POSY>15</POSY>
</JOUEUR>
<ENEMI>
  <POSX>10</POSX>
  <POSY>15</POSY>
</ENEMI>
Tu stocke les objets dans une liste chaînée, pour la parcourrir facilement. En fonction du tag, tu peut créer des objets de type différents, avec des propriétés différentes, tu as besoin dans ce cas d'un numéro de type (enum), et/ou de pointeurs sur fonctions.
Par ex.
struct Enemi
{
  enum TypeEnemi type;
  int posX, posY;
  SDL_Surface tiles[4]; // quatre positions NordSudEstOuest
  int (*action)(struct Enemi*); // pointeur sur fonction ``action`` pour intelligence artificielle
};

Reply

Marsh Posté le 21-04-2006 à 14:29:10    

ca c'est de la réponse :) merci beaucoup j'arrive déjà mieux à me repérer, c'est cool ;)


---------------
http://www.blastmanu.info
Reply

Marsh Posté le 23-04-2006 à 02:00:01    

bonsoir,
 
j'ai commencé par pondre un petit truc, le compilo me retourne aucune erreur mais lors de l'execution c'est le plantage :/
 
je suis complétement largué  :(  
 
main.cpp //pour vous montrer comment je l'utilise

Code :
  1. Map map;
  2.     map.chargementTiles();
  3.     map.aleatoire();
  4.     map.affichage();


 
map.cpp

Code :
  1. include "map.h"
  2. void Map::affichage()
  3. {
  4.     SDL_Rect src, dst;
  5.     int x=0,y=0;
  6.     for(int i=0; i<nb_tile_h;i++)
  7.     {
  8.         x=0;
  9.         for(int j=0; j<nb_tile_w;j++)
  10.         {
  11.             src.x = tiles[map[i][j]].getX();
  12.             src.y = tiles[map[i][j]].getY();
  13.             dst.x = x;
  14.             dst.y = y;
  15.             SDL_BlitSurface(chipset,&src,SDL_GetVideoSurface(),&dst);
  16.             x+=TILE_W;
  17.         }
  18.         y+=TILE_H;
  19.     }
  20. }


 
map.h

Code :
  1. #include "global.h"
  2. #include "tile.h"
  3. class Map
  4. {
  5.     public:
  6.     Map();
  7.     ~Map();
  8.     void chargementTiles();
  9.     void affichage();
  10.     void chargement(string map);
  11.     void aleatoire();
  12.     private:
  13.     SDL_Surface *chipset;
  14.     vector <Tile> tiles;
  15.     vector <vector<int> > map;
  16.     unsigned int width;
  17.     unsigned int height;
  18.     unsigned int nb_tile;
  19.     unsigned int nb_tile_w;
  20.     unsigned int nb_tile_h;
  21. };


 
ce que me dit le debugger:
 

Code :
  1. Selecting target: default
  2. Compiling: done
  3. Starting debugger: done
  4. Adding source dir: C:\Documents and Settings\blastmanu\Mes documents\biguels\
  5. Adding file: SDLapp.exe
  6. Program received signal (SIGSEGV)
  7. Segmentation fault


 
apparemment c'est un pointeur mais j'ai regardé et je ne vois vraimment rien, je désespère là problème avec mes vector ?  [:airforceone]


Message édité par blastman le 23-04-2006 à 18:52:55

---------------
http://www.blastmanu.info
Reply

Marsh Posté le 23-04-2006 à 02:03:11    

j'allais oublier le back-trace me donne ca:
 

Code :
  1. #0 0x00401d59    Tile::setX (??:??)
  2. #1 0x00401965    Map::chargementTiles (??:??)
  3. #2 0x004020f5    SDL_main (??:??)
  4. #3 0x00402920    console_main (win32/SDL_win32_main.c:249)
  5. #4 0x00402ae5    WinMain (win32/SDL_win32_main.c:361)
  6. #5 0x0040241a    main (??:??)


 
en ce qui concerne la classe Tile, il n'y a vraimment rien d'important, l'implémentation est des plus simpliste (du genre return x


---------------
http://www.blastmanu.info
Reply

Marsh Posté le 23-04-2006 à 02:23:13    

Pour trouver ce genre de bug, fait tourner le programme avec le débugger, il te donnera la ligne où se trouve l'erreur.
 
(pour info) fait gaffe avec ça:

Citation :


        nb_tile_w = width/TILE_W;
       nb_tile_h = height/TILE_H;


le résultat de la division est tronqué. Il est préférable de regrouper la définition de WIDTH, TILE_W, et WIDTH/TILE_W, pour les avoir sous les yeux ensemble.
 
> srand(time(NULL));
à ne faire qu'une seule fois en début de programme
 
> affichage() { ...    for()   for()      x=0;
- essaye de mettre l'initialisation avant le deuxième for(). comme tu est en C++, tu peut même déclarer x dans le premier for()

Reply

Marsh Posté le 23-04-2006 à 02:23:13   

Reply

Marsh Posté le 23-04-2006 à 02:34:43    

D'après le trace:
> tiles[i].setX(x);
plante car tiles[i] n'a pas été initialisé. agrandit ton vector avant d'écrire dedans:
http://gcc.gnu.org/onlinedocs/libs [...] 1vectora24
utilise resize()
 
Edit: idem pour: map[i][j] = rand()%nb_tile;


Message édité par nargy le 23-04-2006 à 02:36:38
Reply

Marsh Posté le 23-04-2006 à 13:26:42    


donc voila, j'ai redimentionné les tiles comme ceci:

Code :
  1. tiles.resize(nb_tile);


 
et la map comme cela:

Code :
  1. map.resize(nb_tile_h);
  2.     for(int i=0 ; i < map.size() ; i++)
  3.     {
  4.     map[i].resize(nb_tile_w);
  5.     }


 
je n'est plus d'erreur, la fenêtre s'affiche bien mais reste toute blanche (la map ne s'affiche pas) un erreur dans mon algo. ?! :/


---------------
http://www.blastmanu.info
Reply

Marsh Posté le 23-04-2006 à 13:48:59    

J'ai trouvé ce que j'avais oublié trop content ca marche.
 
Merci beaucoup.


---------------
http://www.blastmanu.info
Reply

Marsh Posté le 23-04-2006 à 15:13:47    

ok, pas de problème :) n'hésite pas si tu as d'autres questions :)

Reply

Sujets relatifs:

Leave a Replay

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