Problem - SDL & OpenGL - Anwendung stürtzt ab / startet nicht richtig



  • Da ich unbedingt plattformunabhängig programmieren wollte, habe ich micht mit OpenGL und SDL beschäftigt. So weit, so gut. Grundsätzlich gab es keine gröberen Schwierigkeiten, aber jetzt wollte ich das ganze mal ein bischen besser programmieren und eine Art Mini-Engine daraus machen.

    Leider scheint da etwas nicht wirklich zu funktionieren, aufjedenfall kommt nach dem starten der Anwendung nur ein schwarzes Fenster. (In der richtigen Größe)
    Mit meiner Klasse für Eventhandling verabschiedet sich das Programm sofort bei jedem Event (Fokuswechsel, Tastendruck, . . .), obwohl der Code eigentlich zu vorher unverändert ist.
    Ohne Eventhandlingklasse kommt zwar mein Fenster, OpenGL wird aber dennoch nicht initalisiert und außerdem bleibt das Programm irgendwie hängen.
    Ich habe schon Stundenlang herumprobiert, bin aber zu keinem wirklichem Ergebnis gekommen.

    Damit ihr wisst von was ich rede:

    main.cpp:

    #include "classes.h"
    
    int main( int argc, char **argv )
    {
        Game *game = new Game(640, 480, 32, false);
        game->run();
    
    	return true;
    }
    

    classes.h (Die Definitionen der Klassen und die Header)

    #include <stdio.h>
    #include <stdlib.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include "SDL.h"
    
    /* screen width, height, and bit depth */
    #define SCREEN_WIDTH  640
    #define SCREEN_HEIGHT 480
    #define SCREEN_BPP     16
    
    /* Define our booleans */
    #define TRUE  1
    #define FALSE 0
    class Game;
    class Eventhandler;
    class Window;
    class gl;
    
    class Eventhandler
    {
    public:
        Eventhandler(Game *gameclass)
        {
            active = true;
            this->gameclass = gameclass;
        }
        void handleEvents();
        void quit();
        bool isActive();
        void changeActive(bool active);
    private:
        Game *gameclass;
        bool active;
        SDL_Event event;
        void handleKeyPress(SDL_keysym *keysym);
    };
    
    class Window
    {
    public:
        Window(int width=640, int height=480, int bpp=32, Game *gameclass=NULL);
        void resize(int width, int height, int bpp=32);
        void toggleFullscreen();
    private:
        Game *gameclass;
        void resizeGL(int widht, int height);
        bool isFullscreen;
        int videoFlags;
        int width;
        int height;
        int bpp;
        const SDL_VideoInfo *videoInfo;
        SDL_Surface *surface;
    };
    
    class Gl
    {
    public:
        Gl(Game *gameclass=NULL);
        void drawFrame();
        Game *gameclass;
    };
    
    class Game
    {
    public:
        Game(int width=640, int height=480, int bpp=32, bool fullscreen=false)
        {
            eventhandler = new Eventhandler(this);
            window = new Window(width, height, bpp, this);
            gl = new Gl(this);
    
            if(fullscreen)
            {
                window->toggleFullscreen();
            }
        }
        void run();
        void resize(int width, int height, int bpp=32);
        void toggleFullscreen();
        void quit();
    private:
        Gl *gl;
        Window *window;
        Eventhandler *eventhandler;
    };
    

    game.cpp (Hauptklasse)

    #include "classes.h"
    
    void Game::run()
    {
        while( this->eventhandler->isActive() )
        {
            this->gl->drawFrame();
            this->eventhandler->handleEvents();
    
        }
    }
    
    void Game::quit()
    {
        SDL_Quit( );
        this->eventhandler->quit();
        exit(true);
    }
    
    void Game::toggleFullscreen()
    {
        window->toggleFullscreen();
    }
    
    void Game::resize(int width, int height, int bpp)
    {
         this->window->resize(width, height, bpp);
    }
    

    window.cpp (Für das Fenstermanagment)

    #include "classes.h"
    
    Window::Window(int width, int height, int bpp, Game *gameclass)
    {
        this->isFullscreen = false;
        this->gameclass = gameclass;
    
        /* initialize SDL */
        if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
        {
            fprintf( stderr, "Video initialization failed: %s\n",
            SDL_GetError( ) );
        }
    
        /* Fetch the video info */
        videoInfo = SDL_GetVideoInfo( );
    
        if ( !videoInfo )
        {
            fprintf( stderr, "Video query failed: %s\n",
            SDL_GetError( ) );
        }
    
        videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
        videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
        videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
        videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */
    
        /* This checks to see if surfaces can be stored in memory */
        if ( videoInfo->hw_available )
        videoFlags |= SDL_HWSURFACE;
        else
        videoFlags |= SDL_SWSURFACE;
    
        /* This checks if hardware blits can be done */
        if ( videoInfo->blit_hw )
        videoFlags |= SDL_HWACCEL;
    
        /* Sets up OpenGL double buffering */
        SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    
        resize(width, height, bpp);
    }
    
    void Window::resize(int width, int height, int bpp)
    {
        if(width>0)
        {
            this->width = width;
        }
    
        if(height>0)
        {
            this->height = height;
        }
    
        if(bpp%2 == 0 && bpp > 0)
        {
            this->bpp = bpp;
        }
    
        if(isFullscreen)
        {
            this->surface = SDL_SetVideoMode( this->width, this->height, this->bpp, this->videoFlags | SDL_FULLSCREEN);
    
            if ( !surface )
    		{
    		    fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
    		    gameclass->quit();
    		}
        }
        else
        {
            this->surface = SDL_SetVideoMode( this->width, this->height, this->bpp, this->videoFlags );
    
            if ( !surface )
    		{
    		    fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
    		    gameclass->quit();
    		}
        }
    
    }
    
    void Window::toggleFullscreen()
    {
        this->isFullscreen = !(this->isFullscreen);
    
        if(isFullscreen)
        {
            this->surface = SDL_SetVideoMode( this->width, this->height, this->bpp, this->videoFlags | SDL_FULLSCREEN);
    
            if ( !surface )
    		{
    		    fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
    		    gameclass->quit();
    		}
        }
        else
        {
            this->surface = SDL_SetVideoMode( this->width, this->height, this->bpp, this->videoFlags );
    
            if ( !surface )
    		{
    		    fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
    		    gameclass->quit();
    		}
        }
    }
    
    void Window::resizeGL(int width, int height)
    {
        /* Height / width ration */
        GLfloat ratio;
    
        /* Protect against a divide by zero */
        if ( height == 0 )
    	height = 1;
    
        ratio = ( GLfloat )width / ( GLfloat )height;
    
        /* Setup our viewport. */
        glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );
    
        /* change to the projection matrix and set our viewing volume. */
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity( );
    
        /* Set our perspective */
        gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
    
        /* Make sure we're chaning the model view and not the projection */
        glMatrixMode( GL_MODELVIEW );
    
        /* Reset The View */
        glLoadIdentity( );
    }
    

    eventhandler.cpp (Für die Events)

    #include "classes.h"
    
    bool Eventhandler::isActive()
    {
        return this->active;
    }
    
    void Eventhandler::changeActive(bool active)
    {
        this->active = active;
    }
    
    void Eventhandler::quit()
    {
        changeActive(false);
    }
    
    void Eventhandler::handleKeyPress(SDL_keysym *keysym)
    {
        switch ( keysym->sym )
    	{
            case SDLK_ESCAPE:
                /* ESC key was pressed */
                gameclass->quit();
                break;
            case SDLK_F1:
                /* F1 key was pressed
                * this toggles fullscreen mode
                */
                gameclass->toggleFullscreen();
                break;
            default:
                break;
    	}
    
        return;
    }
    
    void Eventhandler::handleEvents()
    {
        /* handle the events in the queue */
    
        while ( SDL_PollEvent( &event ) )
    	{
    	    switch( event.type )
    		{
    		case SDL_ACTIVEEVENT:
    		    // Something's happend with our focus
    		    // If we lost focus or we are iconified, we
    		    // shouldn't draw the screen
    
    		    if ( event.active.gain == 0 )
                    changeActive(true);
    		    else
                    changeActive(false);
    		    break;
    		case SDL_VIDEORESIZE:
                //handle resize event
                gameclass->resize(event.resize.w, event.resize.h);
    		    break;
    		case SDL_KEYDOWN:
    		    // handle key presses
    		    this->handleKeyPress( &event.key.keysym );
    		    break;
    		case SDL_QUIT:
    		    /* handle quit requests */
    		    this->quit();
    		    break;
    		default:
    		    break;
    		}
    	}
    }
    

    gl.cpp (Für die OpenGL Sachen - Initalisierung, zeichnen)

    #include "classes.h"
    
    Gl::Gl(Game *gameclass)
    {
        this->gameclass = gameclass;
        /* Enable smooth shading */
        glShadeModel( GL_SMOOTH );
    
        /* Set the background black */
        glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    
        /* Depth buffer setup */
        glClearDepth( 1.0f );
    
        /* Enables Depth Testing */
        glEnable( GL_DEPTH_TEST );
    
        /* The Type Of Depth Test To Do */
        glDepthFunc( GL_LEQUAL );
    
        /* Really Nice Perspective Calculations */
        glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
    }
    
    /* Here goes our drawing code */
    void Gl::drawFrame()
    {
    
        /* Clear The Screen And The Depth Buffer */
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
        /* Move Left 1.5 Units And Into The Screen 6.0 */
        glLoadIdentity( );
        glTranslatef( -1.5f, 0.0f, -6.0f );
    
        glBegin( GL_TRIANGLES );             /* Drawing Using Triangles       */
            glColor3f(0.0f, 0.0f, 1.0f);
            glVertex3f(1.0f, 0.0f, 0.0f);
            glVertex3f(0.0f, 0.0f, 0.0f);
            glVertex3f(0.0f, 1.0f, 0.0f);
        glEnd();
    
    }
    

    Nicht der ganze Code von den SDL Sachen ist von mir, sondern aus einem Tutorial. Ich muss das alles erst mal genauer verstehen. 😉

    Für mich sieht aber der ganze Code ziemlich richtig aus, könnte mir vielleicht bitte jemand sagen wo der Fehler liegt? 😞



  • Der Code ist viel zu lang zum lesen. Versuche mal ein kleines Beispielprogramm zu schreiben, bei dem das Problem auch auftritt. Dann findest du eventuell den Fehler von alleine.

    Edit: also nach und nach alles unnötige aus dem Programm raushauen.



  • Das Problem ist dieses Programm ist aus einem kleinen Beispielprogramm entstanden, bei dem der Fehler nicht aufgetreten ist. Und viel kann ich da nicht entfernen, ohne dass die Struktur mit den Klassen, so wie sie jetzt ist, zerstört wird. Höchstens ein paar Zeilen.

    lg



  • Probiers erstmal mit einem Debugger und steppe einzeln durch das Programm. Dann hast du zumindest eine Chance, den Fehler zu finden. Jeder andere würde es genauso machen, wenn er den Fehler nicht auf den ersten Blick findet.

    Darauf zu hoffen, dass hier jemand vorbei kommt und mit einem Blick den Fehler erfasst, könnte sich als ziemlich enttäuschend rausstellen.

    gruß
    Martin



  • mad_martin schrieb:

    Probiers erstmal mit einem Debugger und steppe einzeln durch das Programm. Dann hast du zumindest eine Chance, den Fehler zu finden. Jeder andere würde es genauso machen, wenn er den Fehler nicht auf den ersten Blick findet.

    So kannst du zumindest den Absturz bei deinem Event Handler finden.



  • Will mir den Code jetzt nicht durchlesen aber:
    Du könntest auch ein paar "verdächtige" Zeilen auskommentieren und einfach testen ob es dann richtig ausgeführt wird...
    Sonst bleibt nur der Debugger oder jmd der sich das ganze durchliest und kontrolliert


Anmelden zum Antworten