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 :

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;
}
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à.

Voici le code qui affiche le texte (utilise SDL_Ttf & OGLFT) :

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
}
à 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é.

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 :

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
}
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
				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 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

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