Jump to content
  • Advertisement
Sign in to follow this  
Anman2

SDL Basis

This topic is 3318 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, With help from NeHe and some other sources I have been trying to create a base for my further SDL projects. I would like your comments on my code. Btw, is it normal to have to create an entirely new window after every resize? Thanks. main.cpp
// Includes
#include "window.h"

Window window;

bool handleInput() {
    if (window.keys[SDLK_a]) {
    }
    return true;
}

bool drawGLScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(-1.5f,0.0f,-6.0f);
    glBegin(GL_TRIANGLES);
		glVertex3f( 0.0f, 1.0f, 0.0f);
		glVertex3f(-1.0f,-1.0f, 0.0f);
		glVertex3f( 1.0f,-1.0f, 0.0f);
	glEnd();
    return true;
}

int main( int argc, char* args[] ) {
    if (!window.createGLWindow(640, 480, 16, false, "test")) {
        exit(1);
    }
    while (window.handleEvents()) {
        if (!window.visible) {
            SDL_WaitEvent(NULL);
        }
        else {
            handleInput();
            drawGLScene();
            SDL_GL_SwapBuffers();
        }
    }
    exit(0);
    return 0;
}
window.cpp
#include "window.h"

Window::Window() {
    screenW = 0;
    screenH = 0;
    screenBPP = 0;
    fullscreen = false;
    title = "";
    visible = true;
    mouseFocus = true;
    inputFocus = true;
}

Window::~Window() {
    SDL_Quit();
}

bool Window::createGLWindow(int width, int height, int bpp, bool full, const string &tit) {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
        return false;
    }
    screenW = width;
    screenH = height;
    screenBPP = bpp;
    fullscreen = full;
    title = tit;
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 5);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	SDL_WM_SetCaption(title.c_str(), title.c_str());

    const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
    if (!videoInfo) {
        fprintf(stderr, "Video query failed: %s\n", SDL_GetError());
        return false;
    }
    videoFlags = SDL_OPENGL | SDL_HWPALETTE | SDL_RESIZABLE;
    if (videoInfo->hw_available) {
        videoFlags |= SDL_HWSURFACE;
    } else {
        videoFlags |= SDL_SWSURFACE;
    }
    if (videoInfo->blit_hw) {
        videoFlags |= SDL_HWACCEL;
    }
    if (fullscreen) {
        videoFlags |= SDL_FULLSCREEN;
    }
    screen = SDL_SetVideoMode(screenW, screenH, screenBPP, videoFlags);
    if (!screen) {
        fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
        return false;
    }
    if (!initGL()) {
        fprintf(stderr, "OpenGL initialization failed: \n");
        return false;
    }
    if (!resizeWindow(screenW, screenH)) {
        fprintf(stderr, "Initial resize failed: \n");
        return false;
    }
    return true;
}

bool Window::handleEvents() {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
            case SDL_QUIT: {
                return false;
            }
            case SDL_KEYDOWN: {
                keys[event.key.keysym.sym] = 1;
                if(keys[SDLK_ESCAPE] == 1) {
                    return false;
                }
				break;
            }
			case SDL_KEYUP: {
				keys[event.key.keysym.sym] = 1;
                break;
            }
            case SDL_VIDEORESIZE: {
                screen = SDL_SetVideoMode(event.resize.w, event.resize.h, screenBPP, videoFlags);
                if (!screen) {
                    fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
                    return false;
                }
                resizeWindow(event.resize.w, event.resize.h);
                break;
            }
            case SDL_ACTIVEEVENT: {
                if (event.active.state & SDL_APPACTIVE) {
                    if (event.active.gain) {
                        visible = true;
                    }
                    else {
                        visible = false;
                    }
                }
                if (event.active.state & SDL_APPMOUSEFOCUS) {
                    if (event.active.gain) {
                        mouseFocus = true;
                    }
                    else {
                        mouseFocus = false;
                    }
                }
                if (event.active.state & SDL_APPINPUTFOCUS) {
                    if (event.active.gain) {
                        inputFocus = true;
                    }
                    else {
                        inputFocus = false;
                    }
                }
            }
        }
    }
    return true;
}

bool Window::initGL() {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    return true;
}

bool Window::resizeWindow(int w, int h) {
    if (h == 0) {
        h = 1;
    }
    glViewport(0, 0, (GLint)w, (GLint)h);
    GLfloat ratio = (GLfloat)w / (GLfloat)h;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, ratio, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    screenW = w;
    screenH = h;
    return true;
}
window.h
#ifndef WINDOW_H
#define WINDOW_H

#include <iostream>
#include <string>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>

using std::string;

class Window {
    public:
        bool visible;
        bool mouseFocus;
        bool inputFocus;
        unsigned int keys[SDLK_LAST];
        Window();
        ~Window();
        bool createGLWindow(int width, int height, int bpp, bool full, const string &tit);
        bool handleEvents();
    private:
        int screenW;
        int screenH;
        int screenBPP;
        bool fullscreen;
        string title;
        SDL_Surface* screen;
        int videoFlags;
        bool initGL();
        bool resizeWindow(int w, int h);
};

#endif

Share this post


Link to post
Share on other sites
Advertisement
I abstracted mine out a bit further, with Game being the main class and Window being a viewport into the game. One thing you may wish to consider is keeping an InputHandler class that gets the latest input for each frame and maybe keeps some more information (such as was the key held down last frame?). You may want to give it checks such as bool InputHandler::IsKeyHeld(int durationMs); InputHandler::QueryLastKeyState(SDL_Key key); etc...

As for create a new windows after resize, no not normally - you normally resize the window itself.

Share this post


Link to post
Share on other sites
In SDL you just call set video mode, and let SDL take care of the details.

Share this post


Link to post
Share on other sites
A few suggestions/observations:

1. There are at least a few good reasons to avoid using global variables in C++ when possible. I won't go into them here, but you can search the forum archives for 'global variables' for more info on this. In this case, you can make window local to main() and then pass it as an argument to handleInput() (and anyone else who needs it).

2. It's generally considered bad practice to include using statements in header files (it pollutes the global namespace wherever the file is included). It would be better to drop the using directive and just qualify the names explicitly (e.g. by typing std::string rather than string).

3. Consider using initializer lists to initialize your class member data.

4. Try to avoid abbreviating your variable names - it just obscures the code and makes it harder for others to understand. 'tit' for title? Can't be bothered to type two more characters? :-) If you're doing this to avoid name clashes, you can use initializer lists instead (within which identical names will resolve unambiguously), or specify the member version using this->.

5. This probably isn't that big a deal, but there's a bit of asymmetry in the fact that you initialize SDL in createGLWindow() rather than the constructor, but shut it down in the destructor. I may be overlooking something here, but my inclination would be to make window local to main() (as mentioned previously), and move the initialization of SDL (but not creation of the window) to the window constructor.

6. Just as a side note, SDL provides a 'key state' array that you can use to query the state of the keyboard at any time - it looks like you may be essentially duplicating this functionality with your key array. Also, I don't see you assigning initial values to the elements of the key array anywhere. And did you perhaps want keys[event.key.keysym.sym] = 0 after case SDL_KEYUP?

Share this post


Link to post
Share on other sites
Give these tutorials a shot: http://sol.gfxile.net/gp/

I learned a hell of a lot from them and they were easier for me to read and and approach.

Share this post


Link to post
Share on other sites
Thanks for your replies. I have adjusted some things according to your suggestions.
I have added a little timing structure to measure the fps of the program. And i notice it caps at 60 fps. Which i think is really low for something that only displays a triangle. What could be causing this, because when i outcomment SDL_GL_SwapBuffers() the fps shoots to something like 14000!

Share this post


Link to post
Share on other sites
Quote:
Original post by Anman2
Thanks for your replies. I have adjusted some things according to your suggestions.
I have added a little timing structure to measure the fps of the program. And i notice it caps at 60 fps. Which i think is really low for something that only displays a triangle. What could be causing this, because when i outcomment SDL_GL_SwapBuffers() the fps shoots to something like 14000!
Is this in fullscreen mode? If so, it's probably due to v-sync being enabled.

Although I think you'll normally want v-sync on in fullscreen mode, you can request that it be turned off (or on) by setting the OpenGL attribute SDL_GL_SWAP_CONTROL before setting the video mode. Note however that depending on your hardware and how the driver is configured, the request may be overridden (that is, v-sync may stay on even though you requested that it be turned off, or vice versa).

Share this post


Link to post
Share on other sites
Vsync is always be enabled in windowed mode IIRC, so you'll get whatever the refresh rate of your monitor is (60Hz). [EDIT: actually, I'm not so sure this is right. Hmm. ]

Commenting out SDL_GL_SwapBuffers means you're not limited to the vsync rate, and since you're not doing anything else time-consuming (/ at all?), you get the crazy high frame rate.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!