Salut !
Le problème exposé plus loin provient sans doute d'une erreur de "C++" de ma part, et non d'une erreur de "SDL". Mais vu la quantité de code SDL je préfère poster ici pour que tout le monde comprenne.
Je commence à coder un RPG 2D depuis quelques jours, mais je suis confronté à un problème incompréhensible. Mon jeu fonctionnait parfaitement, mais voyant qu'il grossissait rapidement, j'ai voulu partager un fichier en deux en leur faisant partager une en-tête commune, mais à partir de là le jeu n'a plus fonctionné comme avant (il n'y a aucun message d'erreur).
Il s'agit donc d'un personnage nommé idiomatiquement "link" qu se déplace sur une carte de (17*17)*32, chaques sprites de décors faisant 32*32 et étant défini par une chaîne de caractères. Il est sensé se déplacer normalement sur les terrains " " et "h", mais il doit être bloqué devant un terrain "H".
Le personnage est géré par la classe Warrior située dans le fichier warrior.cpp, et le terrain par la classe Field stockée dans le fichier field.cpp. Les deux fichiers partagent l'en-tête header.h, qui déclare les classes susnommées.
Le terrain, stocké dans le champ map de la classe Field, contient le contenu d'une variable globale nommée maptest, définissant la carte (avec le système des " ", "h" et "H").
Lors d'un déplacement, la fonction membre getMap() de la classe Field est appellée depuis la fonction membre move() de la classe Warrior, afin de savoir devant quel type de terrain se trouve link. Le troisième argument de getMap vaut soit 0 soit 1, auquel cas les messages de débogages apparaissent sur le fichier de sortie.
Voici la condition posant problème (je montre ici celle executée lors d'un déplacement vers le haut à titre d'exemple). Elle vérifie si link ne se trouve pas devant une salade (terrain "H") à gauche puis à droite.
Les messages de débogages affichent donc parfois des trucs du genre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 if((field.getMap((int)gy/32, (int)gx/32, 0) != "H") && (field.getMap((int)dy/32, (int)dx/32, 0) != "H")) /* Le probleme vient du fait que la condition est toujours consideree comme etanat vraie... */ { /* messages de débogage */ std::cout << "On a a gauche : " << field.getMap((int)gy/32, (int)gx/32, 0); std::cout << ", et a droite : " << field.getMap((int)dy/32, (int)dx/32, 0) << "." << std::endl; std::cout << "-----------------" << std::endl; pos.y -= 2; }
Ce qui signifie qu'on a une salade à gauche et un terrain vide à droite. Cela est complètement illogique puisque la condition ne s'execute que si aucune salade n'est présente à droite et à gauche... Je me permets par ailleurs d'insister lourdement sur le fait que cela fonctionnait correctement avant que je sépare les définitions de classe Warrior et Field (qui étaient avant définies toutes deux dans un classes.cpp), et que le problème ne vient donc pas des calculs.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 On a a gauche : H, et a droite : . -----------
Voici donc le code complet, qui est grand pour moi, mais sans doute tout petit pour vous .
header.h
main.cpp
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 #include <iostream> #include <cstring> #include <SDL/SDL.h> #include <SDL/SDL_image.h> class Warrior; class Field; class Warrior { public: Warrior(); Warrior& move(SDL_Event event, Field field); Warrior& stop(SDL_Event event); SDL_Rect getPos(); SDL_Rect getSize(); SDL_Surface* getSurface(); private: SDL_Rect pos; SDL_Rect size; SDL_Surface* surf; long temps_ecoule; long dernier_temps; }; class Field { public: Field(); const char* getMap(int x, int y, int c = 0); SDL_Surface* getField(); private: char* map[17][17]; /* 17x17 */ SDL_Surface* fields; };
field.cpp
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 #include "header.h" int main ( int argc, char** argv ) { bool done; SDL_Init(SDL_INIT_VIDEO); SDL_EnableKeyRepeat(10, 10); atexit(SDL_Quit); SDL_Surface *ecran = SDL_SetVideoMode(544, 544, 16, SDL_HWSURFACE|SDL_DOUBLEBUF); SDL_Rect fPos, fSize; fSize.w = 32; fSize.h = 32; Warrior link = Warrior(); Field f = Field(); done = false; while (!done) { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: done = true; break; case SDL_KEYDOWN: { switch(event.key.keysym.sym) { case SDLK_ESCAPE: done = true; break; case SDLK_UP: case SDLK_RIGHT: case SDLK_DOWN: case SDLK_LEFT: link.move(event,f); break; } break; } case SDL_KEYUP: { switch(event.key.keysym.sym) { case SDLK_UP: case SDLK_RIGHT: case SDLK_DOWN: case SDLK_LEFT: link.stop(event); break; } break; } } } SDL_FillRect(ecran, 0, SDL_MapRGB(ecran->format, 255, 255, 255)); for(int y = 0; y < 544; y += 32) { for(int x = 0; x < 544; x += 32) { fPos.y = y; fPos.x = x; if( !strcmp(f.getMap(y/32, x/32), " ")) { fSize.x = 0; fSize.y = 0; SDL_BlitSurface(f.getField(), &fSize, ecran, &fPos); } if( !strcmp(f.getMap(y/32, x/32), "H")) { fSize.x = 32; fSize.y = 0; SDL_BlitSurface(f.getField(), &fSize, ecran, &fPos); } if( !strcmp(f.getMap(y/32, x/32), "h")) { fSize.x = 64; fSize.y = 0; SDL_BlitSurface(f.getField(), &fSize, ecran, &fPos); } } } SDL_BlitSurface(link.getSurface(), &link.getSize(), ecran, &link.getPos()); SDL_Flip(ecran); } std::cout << "Exited correctly." << std::endl; return 0; }
warrior.cpp
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
44
45
46
47
48
49
50
51 #include "header.h" char* maptest[17][17] = { {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", "h", "h", "h", "h", "h", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", "h", "h", "H", "H", "h", "h", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", "h", "h", "H", "H", "h", "h", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", "h", "h", "H", "H", "h", "h", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", "h", "h", "h", "h", "h", "h", " ", " ", " ", " ", "h", "h", "h", " ", " ", " "}, {" ", "h", "h", "h", "h", "h", "h", " ", " ", " ", " ", "h", "h", "h", " ", " ", " "}, {" ", "h", "h", "h", "H", "H", "h", " ", " ", " ", " ", " ", "h", "h", " ", " ", " "}, {" ", "h", "h", "h", "H", "H", "h", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", "h", "h", "h", "h", "h", "h", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}, {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "h", "h", "h", "h", "h", " ", " "}, {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "h", "H", "H", "H", "h", " ", " "}, {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "h", "H", "H", "H", "h", " ", " "}, {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "h", "H", "H", "H", "h", " ", " "} }; Field::Field() { fields = IMG_Load("../img/terrain.gif"); for(int j=0; j < 17; ++j) { for(int i=0; i < 17; ++i) { map[j][i] = maptest[j][i]; } } } const char* Field::getMap(int y, int x, int c) { if (c==1) { std::cout << "Les arguments sont : y = " << y << ", x = " << x << "." << std::endl; std::cout << "On retourne : " << map[y][x] << "." << std::endl; } return map[y][x]; } SDL_Surface* Field::getField() { return fields; }
Voilà-voilà. Je connais bien mon code (normal) donc il y a dest trucs que j'ai peut-être omis d'expliquer, n'hésitez pas à me le faire remarquer.
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 #include "header.h" Warrior::Warrior() { pos.x = 544/2 - 30/2; /* 272 + 15 */ pos.y = 544/2 - 32/2; /* 272 + 16 */ size.x = 0; size.y = 0; size.w = 29; size.h = 32; surf = IMG_Load("../img/link.gif"); temps_ecoule = SDL_GetTicks(); dernier_temps = temps_ecoule; } /* ------------------------- Warrior::deplacement --------------------------- */ Warrior& Warrior::move(SDL_Event event, Field field) { double gx, gy, dx, dy; temps_ecoule = SDL_GetTicks(); if(event.type == SDL_KEYDOWN) { switch(event.key.keysym.sym) { case SDLK_UP: /* c'est cette condition que je débogue (j'aurais pu en choisir une autre) */ { gx = pos.x; gy = pos.y; /* -2 ? */ dx = pos.x + 30; dy = pos.y; /* -2 ? */ if((field.getMap((int)gy/32, (int)gx/32, 0) != "H") && (field.getMap((int)dy/32, (int)dx/32, 0) != "H")) /* Le probleme vient du fait que la condition est toujours consideree comme etanat vraie... */ { std::cout << "On a a gauche : " << field.getMap((int)gy/32, (int)gx/32, 0); std::cout << ", et a droite : " << field.getMap((int)dy/32, (int)dx/32, 0) << "." << std::endl; std::cout << "-----------------" << std::endl; pos.y -= 2; } else { std::cout<<"COLLISION !!"<<std::endl; } if(temps_ecoule - dernier_temps > 150) { size.x == 120?size.x = 150:size.x=120; dernier_temps = temps_ecoule; } break; } case SDLK_RIGHT: { gx = pos.x + +28; /* +2 ? */ gy = pos.y; dx = pos.x + 28; /* +2 ? */ dy = pos.y + 32; if((field.getMap((int)gy/32, (int)gx/32) != "H") && (field.getMap((int)dy/32, (int)dx/32) != "H")) { pos.x += 2; } if(temps_ecoule - dernier_temps > 150) { size.x == 240?size.x = 270:size.x=240; dernier_temps = temps_ecoule; } break; } case SDLK_LEFT: { gx = pos.x; /* -2 ? */ gy = pos.y; dx = pos.x; /* -2 ? */ dy = pos.y + 32; if((field.getMap((int)gy/32, (int)gx/32) != "H") && (field.getMap((int)dy/32, (int)dx/32) != "H")) { pos.x -= 2; } if(temps_ecoule - dernier_temps > 150) { size.x == 180?size.x = 210:size.x=180; dernier_temps = temps_ecoule; } break; } case SDLK_DOWN: { gx = pos.x; gy = pos.y + 30; /* +2 ? */ dx = pos.x + 30; dy = pos.y +30; /* +2 ?*/ if((field.getMap((int)gy/32, (int)gx/32) != "H") && (field.getMap((int)dy/32, (int)dx/32) != "H")) { pos.y += 2; } if(temps_ecoule - dernier_temps > 150) { size.x == 30?size.x = 60:size.x=30; dernier_temps = temps_ecoule; } break; } } } else { std::cerr << "Erreur incomprehensible... Argument event n'etait pas du type attendu." << std::endl; } return *this; } Warrior& Warrior::stop(SDL_Event event) { if(event.type == SDL_KEYUP) { switch(event.key.keysym.sym) { case SDLK_UP: { size.x = 90; break; } case SDLK_RIGHT: { size.x = 240; break; } case SDLK_LEFT: { size.x = 180; break; } case SDLK_DOWN: { size.x = 0; break; } } } else { std::cerr << "Erreur incomprehensible... Argument event n'etait pas du type attendu." << std::endl; } return *this; } /* ---------------------------- Warrior::Image ------------------------------ */ SDL_Rect Warrior::getPos() { return pos; } SDL_Rect Warrior::getSize() { return size; } SDL_Surface* Warrior::getSurface() { return surf; }
En espérant que vous puissiez m'aider.
Partager