Skip to main content
gamedev.net
🔒 Locked

Keepin' it moving (Windows)

Started by Shon Jan 23, 2005 at 1:05 AM 2 replies 1.4k views
Original Post
Shon
Shon
Well, this probably isn't even necessary if you just make the thing full screen but... it's driving me crazy. Does anyone know a way to keep the program running and drawing OpenGL stuff despite the fact that the user may be moving the window around in MS Windows? I've tried using GetMessages, tried it with and without the yields... tried using Windows' Sleep function... Everything works slightly differently and nothing gets me what I want... a triangle that keeps moving despite the fact that the user is dragging the window around. Is there something I'm missing here? =/ Here's the meat of the code that I'm working with... if anyone can see what I'm doing wrong... I will be VERY grateful for my continued sanity! ^_^;
//--Includes--//
int main ( int argc , char* argv [] )
{
    boost::thread win_thread(WindowThread);

    //Wait for Window to be ready
    while (!win_ready) {win_thread.yield();};

    StartUp();

    while (!quit_flag) {
        GameLoop();
    }

    ShutDown();

    win_thread.join();
    return ( 0 ) ;
}

void StartUp() {
    //--Graphics--//
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(pfd));

    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cRedBits = 8;
    pfd.cBlueBits = 8;
    pfd.cGreenBits = 8;
    pfd.cAlphaBits = 8;
    pfd.cDepthBits = 16;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int format_id = ChoosePixelFormat(win_hdc, &pfd);

    SetPixelFormat(win_hdc, format_id, &pfd);

    gl_cont = wglCreateContext(win_hdc);
    wglMakeCurrent(win_hdc, gl_cont);

    //Set up projection
    glViewport(0, 0, 640, 480);

    glMatrixMode(GL_PROJECTION);                // Select The Projection Matrix
    glLoadIdentity();                            // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    gluPerspective(45.0f,(GLfloat)640/(GLfloat)480,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);                    // Select The Modelview Matrix
    glLoadIdentity();                
}

void ShutDown() {
    wglDeleteContext(gl_cont);
}

void GameLoop() {
        //Clear the Screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        glTranslatef(0.0f,0.0f,-5.0f);
        glRotatef(r_angle, 1.0f, 0.0f, 0.0f);
        glRotatef(r_angle, 0.0f, 1.0f, 0.0f);
        glRotatef(r_angle, 0.0f, 0.0f, 1.0f);
                
        //Draw triangle
        glColor3f(1.0,1.0,1.0);
        glBegin(GL_TRIANGLES);                        // Drawing Using Triangles
            glVertex3f( 1.0f, -1.0f, 0.0f);                // Top
            glVertex3f(-1.0f,-1.0f, 0.0f);                // Bottom Left
            glVertex3f( 0.0f,1.0f, 0.0f);                // Bottom Right
        glEnd();    

        r_angle += 0.1f;

        //Present
        SwapBuffers(win_hdc);
        //Wait a bit
        boost::thread dummy;
        dummy.yield();
}

void WindowThread () {
    //--Create Window Class--//
    WNDCLASSEX win_class;
    memset(&win_class, 0, sizeof(win_class));

    win_class.cbSize = sizeof(win_class);
    win_class.style = NULL;
    win_class.lpfnWndProc = WinProc;
    win_class.cbClsExtra = 0;
    win_class.cbWndExtra = 0;
    win_class.hInstance = app_inst;
    win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    win_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    win_class.lpszMenuName = NULL;
    win_class.lpszClassName = "RPG Demo";
    win_class.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    //Register class
    if (!RegisterClassEx(&win_class))
        throw runtime_error("Failed to register Window Class");

    //--Create Window--//
    RECT win_rect;
    win_rect.left = 0;
    win_rect.top = 0;
    win_rect.right = win_width;
    win_rect.bottom = win_height;
    
    //For Windowed
    DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
    DWORD dwStyle = WS_OVERLAPPEDWINDOW;

    AdjustWindowRectEx(&win_rect, dwStyle, FALSE, dwExStyle);

    if (!(win_handle = CreateWindowEx(0,                  // extended style
                                "RPG Demo",     // class
                                "RPG Demo - www.liztail.com", // title
                                dwStyle | WS_VISIBLE,
                                 0, 0,      // initial x,y
                                win_rect.right - win_rect.left, win_rect.bottom - win_rect.top,  // initial width, height
                                0,      // handle to parent
                                0,      // handle to menu
                                app_inst,// instance of this application
                                0)))    // extra creation parms
        throw runtime_error("Failed to create Window");
    
    //Get DC
    win_hdc = GetDC(win_handle);

    win_ready = true;

    //--Event Loop--//
    MSG    msg;
    while(true) {
        while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
            if (msg.message==WM_QUIT) {
                // Quit Message
                quit_flag = true;
                return;
            }
            else {
                //Default Processing
                TranslateMessage(&msg);                // Translate The Message
                DispatchMessage(&msg);                // Dispatch The Message
            }
            boost::thread dummy;
            dummy.yield();
        }
    }
}
--Shon
Gorax
Gorax
The only way to do that is to split the rendering/updating thread from the event thread. If you plan on doing that, you'll have to make sure that one thread's not deleting something another one's reading. Basically, it's a lot of work for something that isn't all that important.

Another way to keep it moving, although not visibly, would be to rotate it by some amount per second, that way even if the window does nothing but accept event messages for a whole minute, when it does start rendering again, it would have rotated the triangle that amount * the time passed, so it'd be in the appropriate position.
Shon
Shon
Thanks for your reply! I did in fact split it into two threads, but your comment got me to thinking about something. There MUST be some sort of dependency between what I'm doing in the GameLoop function and what I'm doing in the WindowThread one.

Well, I think I figured out what it is, but it's hard to know if anything can be done about it. The only non-OpenGL function that I was calling in GameLoop was this one:

SwapBuffers(win_hdc);

I moved it over into the other thread, and now, sure enough, while the triangle still stops moving when I drag the window around, when I stop moving the window it jumps in position, obviously having been rotating in the background the whole time.

Soo... does that mean there's no way to call SwapBuffers while the window is being moved around? =/

Would I have to make another borderless window that automatically followed the main one at regular intervals to put that call back into the GameLoop function? Maybe that's why Windows Media Player sometimes can be moved away from the display area...
--Shon
Shon
Shon
Well, I reached a solution that is at least acceptable.

Basically I'm catching these messages and using them to set a flag that causes the GameLoop function to skip calling SwapBuffer:

case WM_ENTERSIZEMOVE:    win_moving = true;    return 0;break;case WM_EXITSIZEMOVE:    win_moving = false;    return 0;break;[...]if (!win_moving) {    SwapBuffers(win_hdc);}


I figure that, at least this way, if I were to encapsulate the calls, the client wouldn't get a nasty surprise when the Swap function turned out to be blocking.

Does anyone know of a better solution? I tried making a second window, and moving it didn't cause the animation on the first window to stop... but it did slow it down tremendously =/ Is there any way to force a particular window to move and size using the Sizing Rectangle instead of the WindowsXP way?
--Shon

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.