PDA

Voir la version complète : Allocation dynamique bug dans SDL


TrizoLakai
29/08/2005, 10h59
J'ai fais un fichier test que j'ai compilé pour essayé l'allocation dynamique d'un tableau à 2 dimensions. Le voici :

#include <iostream>

using namespace std;


int main(){
FILE *carte;

unsigned int **map;
unsigned int taille_x;
unsigned int taille_y;
unsigned int tableau[10][10];

/* Chargement de la carte */
carte = fopen("../../DATA/map/map1.dat", "r");
fscanf(carte, "%d %d\n", &taille_x, &taille_y);

/* Allocation dynamique du tableau map */
map = new unsigned int*;
for(int i = 0; i < taille_x; ++i)
map[i] = new unsigned int[taille_y];

for(int i = 0; i < taille_y; ++i){
for(int j = 0; j < taille_x; ++j){
fscanf(carte, "%d ", &map[j][i]);
tableau[j][i] = map[j][i];
}
}

fclose(carte);

/* Affichage de la carte */
for(int j = 0; j < taille_y; ++j){
for(int i = 0; i < taille_x; ++i){
cout << map[i][j] << " ";
}
cout << endl;
}

system("Pause");
delete map;
for(int i = 0; i < taille_x; ++i)
delete[] map[i];


return 0;
}

Ce code fonctionne parfaitement. Mais quand je l'implente à mon mini projet de RPG. Il y a une erreur. J'ai regardé à partir de quand. Et cette erreur survien lorsque l'on essais de mettre un nombre dans le tableau au dessus de map[4][0]. Je ne comprend pas pourquoi. Voici le code :

void LoadMap(SDL_Rect &Rect_Placement){
FILE *carte;

carte = fopen("./DATA/map/map1.dat", "r");
fscanf(carte, "%d %d\n", &taille_x_map, &taille_y_map);

map = new unsigned int*;
for(int i = 0; i < taille_x_map; ++i)
map[i] = new unsigned int[taille_y_map];

for(int j = 0; j < taille_y_map; ++j){
for(int i = 0; i < taille_x_map; ++i){
map[i][j] = 0;
}
}

fclose(carte);

carte = fopen("./DATA/map/map1d.dat", "r");
for(int j = 0; j < taille_y_map; ++j){
for(int i = 0; i < taille_x_map; ++i){
fscanf(carte, "%d ", &donnee[i][j]);
}
}
fclose(carte);

for(int j = 0; j < taille_y_map; ++j){
for(int i = 0; i < taille_x_map; ++i){
if(donnee[i][j]==2){
Rect_Placement.x = 4+i*30;
Rect_Placement.y = j*32-30;
}
}
}
}

Voici la ligne qui l'appel dans (dans une source séparée) :
LoadMap(Rect_Placement);

Merci pour votre aide. Je suis vraiment bloqué et je ne comprend pas d'où viens le problème :00000032:

Merci encore.

remram44
29/08/2005, 11h23
map = new unsigned int*;
for(int i = 0; i < taille_x; ++i)
map[i] = new unsigned int[taille_y];

map = new unsigned int*[taille_x];

Le dépassement d'indice ne produit pas forcement d'erreur, par contre SDL le voit à chaque fois, et produit une segmentation fault.

Sinon, pour utiliser un tableau à deux dimensions, j'aurai plutôt fais comme ça :

class CMap {
unsigned int* map; // Pointeur simple, une seule *
int taille_x;
int taille_y;

public:
CMap();
void Set(int,int,unsigned int);
unsigned int Get(int,int);
};

// ...

CMap::CMap(x,y)
{
taille_x=x;
taille_y=y;
map = new unsigned int[taille_x*taille_y];
}

unsigned int CMap::Get(int x,int y)
{
return map[(taille_x*y)+x];
}

void CMap::Set(int x,int y,unsigned int m)
{
map[(taille_x*y)+x]=m;
}

TrizoLakai
29/08/2005, 11h31
Génial ta premier solution fonctionne. Je ne suis pas trés doué en C++, alors juste une question. C'est parce que j'avais oublié de créer le tableau qui contien le seconde ?

Sinon pour ta seconde solution :

unsigned int* map; // Pointeur simple, une seule *
map = new unsigned int[taille_x*taille_y];

Je croi qu'il ne comprend pas le map[x][y], dans la suite du programme, car je site l'erreur de compilation :

22 H:\Cpp\Projets\RPG ShamanKing\DEV-Cpp\Test\test alloc dyn tableau.cpp invalid types `unsigned int[int]' for array subscript

Merci pour ton aide et ta future réponse.

remram44
29/08/2005, 12h38
Oui, j'ai édité mon code. Dans ce cas, il faut bien sûr faire sa propre fonction d'accès à une certaine cellule du tableau.

TrizoLakai
29/08/2005, 13h16
Ok mais je préfère un tableau simple pour l'instant. Je vois que tu utilises les classes. Dernière question (enfin je crois :D) :

Pourquoi utiliser des classes ? C'est plus performants ?

Ced666
29/08/2005, 13h32
Euuh, ben c'est surtout que c'est une façon complètement différente de programmer. Tu défini des objets qui interragissent entre eux au lieu d'avoir du code 'procédural'. Ca permet de regrouper des fonctionnalité dans des objets et au final, tu obtiens un code beaucoup plus propre (peut-être un peu plus compliqué pour un débutant mais également extrêment plus souple).

TrizoLakai
29/08/2005, 13h36
J'ai déjà essayé mais jeme retrouvé avec des classes géante qui en fait regroupé presque tout :00000032: .

Je verai tout cela plus tard. Un code en "procédural" est long à retranscrire en "objet/classe" ? :??:

merci pour vos réponses

redman
29/08/2005, 13h50
Pour les tableaux, le mieux est d'utiliser les 'vectors' de la librairie standard. Le but est justement de permettre l'allocation dynamique, etc...

#include <vector>
#include <iostream>

using namespace std;

vector<int> tableau //tableau d'entiers

tableau.push_back(); //ajoute 1 au tableau
tableau.push_back(); //ajoute 10 au tableau

cout << tableau[0] << endl; //le premier élément du tableau, cad 1
cout << tableau[1] << endl; //le 2eme élément, cad 10

tableau.erase(0); //supprime le premier élément, le 1

voila en gros...

Redman

TrizoLakai
29/08/2005, 13h59
J'ai rien compris à ton exemple :00000012: . Je vais me renseigner sur les "vectors".;)

TrizoLakai
29/08/2005, 14h03
Voila j'ai encore un bug assez génant dans SDL.

ce code. Pour ajouter son nom (Voir topic dans la même catégorie) fonctionne en fenètré. Mais dés que l'on passe en FULLSCREEN ça ne fonctionne plus.

void NickName(SDL_Event *event, SDL_Surface *Screen, SDL_Surface *fond){
bool ecriture = true;
static SDL_Rect Rect_TTF;
static TTF_Font *Font_Texte=NULL;
static SDL_Surface *Text_Surface;
static SDL_Rect Rect_Placement, Rect_Fond;

Rect_TTF.x = 95;
Rect_TTF.y = 265;
Rect_Fond.x = 0;
Rect_Fond.y = Rect_TTF.y;

SDL_Color Couleur_Texte={250,100,0};
if(Font_Texte==NULL)Font_Texte = TTF_OpenFont("./police.ttf", 20);

char Lettre_Joueur[20]; int Nb_Lettre = 0;
sprintf(Lettre_Joueur, " ");

while(ecriture){
SDL_PollEvent(event);
SDL_EnableUNICODE(1);
if(event->type == SDL_MOUSEBUTTONUP){
ecriture = false;
}
if(event->key.state==SDL_PRESSED){
if(event->key.keysym.unicode==SDLK_BACKSPACE){
if(Nb_Lettre > -1)--Nb_Lettre;
Rect_Fond.x = Nb_Lettre*10 + Rect_TTF.x;
Rect_Fond.w = 350 - Nb_Lettre*10 + Rect_TTF.x;
Rect_Fond.h = 50;
Lettre_Joueur[Nb_Lettre] = ' ';
SDL_BlitSurface(fond, &Rect_Fond, Screen, &Rect_Fond);
}
else {
if(Nb_Lettre == 20){
Rect_Fond.x = Nb_Lettre*10 + Rect_TTF.x;
Rect_Fond.w = 350 - Nb_Lettre*10 + Rect_TTF.x;
Rect_Fond.h = 50;
SDL_BlitSurface(fond, &Rect_Fond, Screen, &Rect_Fond);
Nb_Lettre = 19;
}
Lettre_Joueur[Nb_Lettre] = event->key.keysym.unicode;
++Nb_Lettre;
}
Text_Surface = TTF_RenderText_Solid(Font_Texte, Lettre_Joueur, Couleur_Texte);
SDL_BlitSurface(Text_Surface, NULL, Screen, &Rect_TTF);
SDL_Flip(Screen);
}
SDL_Delay(70);
}
}

J'ai essayé de mettre des

cout << event->motion.x << " ; " << event->motion.y <<endl;

et j'ai remarqué que le event->motion me renvoyé desfois des coordonnées fausses. Toujours les même en plus : 35 en y et un nombre au deçut de 10 000 pour les x. :00000023:

Une idée du problème?
Je rapel que ce code fonctionne si je ne passe pas en FULLSCREEN

TrizoLakai
29/08/2005, 14h16
J'ai rien compris à ton exemple :00000012: . Je vais me renseigner sur les "vectors".;)

c'est parce que tu avais oublié l'entier dans tableau.push_back(ici);

Sinon je ne peut pas m'en servir parce que je voudrai un tableau en 2 dimension. Alors que "ton" vector ne permet qu'une dimension.

je prefère en garder mes tableaux.

TrizoLakai
29/08/2005, 22h34
Apparament on peut faire des vector en deux dimensions : vector<vector<int>> blabla

mais trop compliqué.

Sinon vous avez une idée pour mon FULLSCREEN ? (voir plus haut)