Bonjour,
je développe actuellement un petit moteur de jeu 2D basé sur SDL & OpenGL mais j'ai quelques petits problèmes de plantages et de vitesse d'execution.
Voici un simple programme crée avec mon moteur qui affiche une série de raquette sur toutes la hauteur de l'écran et les fps... seulement, le programme plante méchamment avec OpenGL où SDL après un premier tour de boucle et je vois pas trop pourquoi :
Si je commente la ligne de l'affichage de la font le programme ne plante plus donc je pense que le problème vient de là.
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 #include <ES/ES_Display/graphics.h> #include <ES/ES_Display/ttf.h> #include <ES/ES_Event/event.h> #include <ES/ES_Utils/utils.h> #define R_MODE ES_SDL int main(int argc, char *argv[]) { int x_img= 0, y_img = 0, vel_x = 1; unsigned int check_time = 0, fps = 0; ES_Resources res; ES_Event event; ES_Graphics *graphics = new ES_Graphics("ES - TestApp", 640, 480, 32, false, R_MODE, true); if(R_MODE == ES_OPENGL) { graphics->opengl_init(); graphics->set_orto_view(); } ES_Ttf *font = new ES_Ttf(); font->set_size(18); res.add_resource("global font", "arial.ttf", ES_TTF_FONT); res.add_resource("test img", "img.png", ES_IMG, true, 255, 0, 255); event.set_key_repeat(100, 2); long time = SDL_GetTicks(); while(graphics->run()) { check_time = SDL_GetTicks(); graphics->clear_screen(); while(event.poll_event()) { switch(event.get_event_type()) { case SDL_QUIT: graphics->quit(); break; } } for(int i = 0; i < graphics->get_window_height(); i+=16) { graphics->draw_image("test img", graphics->rect(0, 0, 64, 16), graphics->rect(x_img, y_img+i, 64, 16), true); } if(x_img > graphics->get_window_width()-64) vel_x = -vel_x; else if(x_img < 0) vel_x = -vel_x; x_img += vel_x; font->draw_text("global font", "FPS: "+to_string(fps), graphics->get_window_width(), 0, graphics->color(255, 255, 255, 0), ES_RIGHT); if(SDL_GetTicks()-time>=150) { fps = 1000/(SDL_GetTicks()-check_time); time = SDL_GetTicks(); } graphics->flip(5); } res.clear_resources(); delete font; delete graphics; return EXIT_SUCCESS; }
Voici le code qui affiche le texte (utilise SDL_Ttf & OGLFT) :
à noter que si j'affiche autre chose que les fps (genre la valeur d'une autre variable) ça ne plante pas, ça viendrait peut être du calcul du fps non ? seulement j'ai testé la fonction qui calcule les fps trouvé sur un sujet du forum et ça n'as pas fonctionné.
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 void ES_Ttf::draw_text(const std::string& resource_name, const std::string& text, short int x, short int y, SDL_Color color, unsigned short int justification, unsigned short int style, SDL_Color color_bg) { #ifdef ES_USE_OPENGL if(ES_OpenGL_Mode == false) { #endif if(resources.get_sttf_font(resource_name) != 0) { TTF_SizeText(resources.get_sttf_font(resource_name), text.c_str(), &font_width, &font_height); switch(justification) { case ES_CENTER: horizontal_justification = font_width/2; break; case ES_LEFT: horizontal_justification = 0; break; case ES_RIGHT: horizontal_justification = font_width; break; default: break; } pos.x = x-horizontal_justification; pos.y = y-font_height/3; switch(style) { case ES_SOLID: // rapide txt = TTF_RenderText_Solid(resources.get_sttf_font(resource_name), text.c_str(), color); break; case ES_SHADED: // moyenement rapide, arriére plan non transparent (rendu lisse) txt = TTF_RenderText_Shaded(resources.get_sttf_font(resource_name), text.c_str(), color, color_bg); break; case ES_BLENDED: // assez lent mais meilleur qualité (rendu lisse + colorkey) txt = TTF_RenderText_Blended(resources.get_sttf_font(resource_name), text.c_str(), color); break; default: break; } SDL_BlitSurface(txt, NULL, SDL_GetVideoSurface(), &pos); SDL_FreeSurface(txt); } #ifdef ES_USE_OPENGL } else { if(resources.get_gl_font(resource_name) != 0) { switch(justification) { case ES_CENTER: resources.get_gl_font(resource_name)->setHorizontalJustification(OGLFT::Face::CENTER); break; case ES_LEFT: resources.get_gl_font(resource_name)->setHorizontalJustification(OGLFT::Face::LEFT); break; case ES_RIGHT: resources.get_gl_font(resource_name)->setHorizontalJustification(OGLFT::Face::RIGHT); break; default: break; } resources.get_gl_font(resource_name)->setVerticalJustification(OGLFT::Face::TOP); resources.get_gl_font(resource_name)->setForegroundColor(color.r, color.g, color.b); glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glPushMatrix(); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTranslatef(x, y, 0.); glRotatef(180., 1., 0., 0.); resources.get_gl_font(resource_name)->draw(0, 0, text.c_str()); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPopMatrix(); } } #endif }
Ensuite, j'ai un problème de vitesse d'execution entre OpenGL et SDL, j'ai l'impression qu'OpenGL tourne vraiment plus lentement que SDL, j'ai pensé au début que ça pourraît être à cause que du cast en int à l'affichage et apparement c'est bien ça, mais je sais pas très bien comment résoudre ça, j'aurait penser que appeller glVertex2i au lieu des 2f et compagnie aurait pu résoudre le problème mais ça n'est pas le cas.
Voici le code qui affiche une image avec SDL où OpenGL :
Aussi, j'utilise un systéme de ressources génériques grâce au conteneur map de la stl pour charger mes images/fonts etc... mais je pense avoir un petit problème de gestion mémoires, dans ce morceau de code je charge une image avec SDL_image puis je la convertit au format de l'écran et ensuite je place la surface dans mon conteneur avec le texte (clé) associé, seulement j'ai pas l'impression que je libére correctement la surface imageo_temp à chaque fois ? si je fais un SDL_FreeSurface(imageo_temp) après img[resource_name] = imageo_temp; mes images ne peuvent plus s'afficher, comment faire pour libérer correctement cette surface après l'avoir copié dans mon conteneur ? :
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 void ES_Graphics::draw_image(const std::string& resource_name, SDL_Rect src, SDL_Rect rect, bool blend) { if(opengl_mode == false) // affiche avec sdl SDL_BlitSurface(resources.get_sdl_img(resource_name), &src, screen, &rect); #ifdef ES_USE_OPENGL else // affiche avec opengl { pos_x = rect.x; pos_y = rect.y; w = rect.w; h = rect.h; glLoadIdentity(); if(blend == true) { glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); } glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, resources.get_opengl_img(resource_name)); glBegin(GL_QUADS); glTexCoord2i(0,0); glVertex2i(pos_x,pos_y); glTexCoord2i(1,0); glVertex2i(pos_x+w,pos_y); glTexCoord2i(1,1); glVertex2i(pos_x+w,pos_y+h); glTexCoord2i(0,1); glVertex2i(pos_x,pos_y+h); glEnd(); glDisable(GL_TEXTURE_2D); if(blend == true) glDisable(GL_BLEND); } #endif }
Pour ceux qui veulent tester pour la vitesse d'execution entre OpenGl et SDL avec mon moteur j'ai fait un petit Pong d'exemple qui est disponible ici : http://www.garzul.tonsite.biz/ES/ES_Pong.zip
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 image_temp = IMG_Load(resource_filename.c_str()); if(image_temp == 0) std::cerr << "_Can't load img: \"" << resource_filename.c_str() << "\" -> " << SDL_GetError() << std::endl; else { imageo_temp = SDL_DisplayFormat(image_temp); // convertit la surface au format de l'écran SDL_FreeSurface(image_temp); if(imageo_temp!=NULL) { img[resource_name] = imageo_temp; if(colorkey == true) SDL_SetColorKey(img[resource_name], SDL_RLEACCEL | SDL_SRCCOLORKEY, SDL_MapRGB(img[resource_name]->format, r, g, b)); } else std::cerr << "_Can't convert img surface: \"" << resource_filename.c_str() << "\" -> " << SDL_GetError() << std::endl; }
Pour passer en rendu OpenGL éditer le fichier config.xml et remplacer sdl par opengl
La page du moteur est ici : http://www.garzul.tonsite.biz/wiki/
Merci d'avance pour vos réponses
Partager