Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: AGL_SWAP_INTERVAL problems




Matthew Beedle wrote:


I to handle my game at an interval of 60 fps, but let it draw in sync with the display's refresh rate.
I used AGL_SWAP_INTERVAL for a long while.
If I handle the game at 60 fps and the monitor refresh rate is 60Hz, everything is fine.
The problem is, if I want to handle the game at 60 fps and the monitor refresh rate is 75Hz, the animation is no longer very smooth.
Going into full screen mode and setting the refresh rate to 60Hz doesn't work on all displays. Also, it is a very common feature these days run the game in window mode.
The question is, how can I let be game be handled at 60 fps, while drawing at whatever the monitor's refresh rate is, without impacting performance of the game (assuming the hardware can keep up.)
I have put together a small demo.
http://www.foxchange.com/matt/temp/refreshSyncProblem.sit



In your demo you have an EventLoopTimer to call your game calculations at regular intervals --- of order 1/60s --- and a second timer that calls aglSwapBuffers() at regular intervals, also of order 1/60s. That approach won't properly synchronize (or more accurately, serialize) the successive phases of the game cycle.


I suggest that you write a central function like OneCycleOfMyGame below, and call it from a single EventLoop timer. The pseudo C code assumes one common way to represent a moving object or sprite, namely a struct that specifies position, velocity and no doubt additional variables. Position is updated every frame, using the velocity as determined by your UI, gravity, collisions and so on. Position and velocity have x and y components (and z, for 3D).

void OneCycleOfMyGame( void )
{
    /* Elapsed interval */
    static double  sLastT = 0.0;
    double         currentT, deltaT;
    if ( sLastT == 0.0 ) sLastT = MyCurrentDoubleTime();
    currentT = MyCurrentDoubleTime();
    deltaT   = currentT - sLastT;
    sLastT   = currentT; // for next cycle

    /* Game calculations */
    for ( each sprite )
    {
        sprite->velocity = MySpriteVelocityCalc( sprite );
        sprite->position += sprite->velocity * deltaT;
    }

    /* Draw a frame */
    MyOpenGLStartDrawingFrame(...);
    for ( each sprite )
    {
        MyOpenGLDrawSpriteFunction( sprite );
    }
    MyOpenGLFinishDrawingFrame(...);

    /* Show the frame */
    aglSwapBuffers( gMyOpenGLContext );
}

int main( void )
{
    MyInitializeGame();
    // Set up an EventLoopTimer to call OneCycleOfMyGame
    // every 1 ms (the real interval will be much longer).
    MyInstallTimer( kEventDurationMillisecond, OneCycleOfMyGame );
    RunApplicationEventLoop();
    return 0;
}

OneCycleOfMyGame() ensures that everything is done at the right time and in the right order. Moreover, it automatically makes the speed of sprite movement independent of frame rate (which is why you use the sprite's velocity and deltaT in calculating the new position). To a first approximation, you don't need to worry about the actual frame rate, as long as it's not so low as to make the movement jerky or so high as to heat up the processor unnecessarily.

Robert P.


_______________________________________________ Do not post admin requests to the list. They will be ignored. Mac-opengl mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/mac-opengl/email@hidden

This email sent to email@hidden
References: 
 >AGL_SWAP_INTERVAL problems (From: Matthew Beedle <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.