Thread: Handling logic and draw cycles

  1. #1
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743

    Handling logic and draw cycles

    So a friend of mine and I are working on a game project (and have been for a few months now) based on the little army men figurines that many of us have probably played with before as kids (or as adults!).

    If you don't know what I am talking about, check out this image I found doing a quick search on Google Images:

    http://ecx.images-amazon.com/images/...500_AA280_.jpg

    Anyways...

    We have got quite a lot of the back end done, but we were not happy with the performance we were getting. Of course...we initially hadn't coded our back end for performance, but for functionality. Now, having gotten an acceptable amount of functionality in, I went back and revamped a lot of things to increase performance. The most notable - and obvious - change was to simply use display lists for rendering our models on the screen every frame. Initially we weren't using them. After the implementation of display lists, our frame rate went from roughly 45 fps up to 150 fps.

    Now, after I implemented that, I wanted to revamp how we were handling the actual drawing and logic in the game. Up until this point, we just had a simple loop that spun around and tried to do logic and drawing every single frame as fast as possible, as I am sure you have all seen and done before, like this:

    Code:
    while ( MessageLoop ( event ) )
    {
        TickClock ( );
        RunLogic();
        DrawObjects();
    }
    I wanted to make it so that everything gets drawn a fixed number of times per second, and so that the logic happens a fixed number of times per second, ...since that is the proper way to do things anyways..., and it makes the game less susceptible to differences in performance of two different computers.

    So I edited the TickClock() function to let me know at certain intervals when I should do the draw phase and when I should do the logic phase. I interlace the two, and never do them at the same time. Now it looks like this:

    Code:
    while ( MessageLoop ( event ) )
    {
        TickClock ( );
        if ( logicFrame ) RunLogic();
        if ( drawFrame ) DrawObjects();
    }
    logicFrame and drawFrame will each be true every 8/1000 of a second, but they switch off, so each one runs roughly 65 times a second right now.

    Anyways, so here are my stats:

    Before doing anything (including display lists): everything at about 45 fps

    After display lists: everything at 150 fps

    After making the timing adjustments:
    The main loops runs between 10000 and 20000 times per second.
    Logic and graphics each run very consistently 65 times per second.

    I was wondering if you have any suggestions on my implementation of things, particularly how I have done my timer. Here is the code for the actual TickClock() function:

    Code:
    void SIMULATION::TickClock ( void )
    {
    	static int waitTime = 8;
    	static int prevSecond = clock();
    	static int prevDrawFrame = clock();
    	static int prevLogicFrame = prevDrawFrame + (waitTime / 2);
    	int newTime = clock();
    
    	loopFrameCount++;
    	drawFrame = false;
    	logicFrame = false;
    
    	if ( newTime > (prevDrawFrame + waitTime) )
    	{
    		drawFrame = true;
    		prevDrawFrame = newTime;
    	}
    
    	if ( newTime > (prevLogicFrame + waitTime) )
    	{
    		logicFrame = true;
    		prevLogicFrame = newTime;
    	}
    
    	if ( newTime > (prevSecond + CLOCKS_PER_SEC) )
    	{
    		prevSecond = newTime;
    
    		char loopFrameCstr[10];
    		char graphicsFrameCstr[10];
    		char logicFrameCstr[10];
    
    		sprintf_s(loopFrameCstr, "%d", loopFrameCount);
    		loopFrameString = "Clock Frames: " + string(loopFrameCstr);
    
    		sprintf_s(graphicsFrameCstr, "%d", graphicsFrameCount);
    		graphicsFrameString = "Graphics Frames: " + string(graphicsFrameCstr);
    
    		sprintf_s(logicFrameCstr, "%d", logicFrameCount);
    		logicFrameString = "Logic Frames: " + string(logicFrameCstr);
    
    		loopFrameCount = 0;
    		graphicsFrameCount = 0;
    		logicFrameCount = 0;
    	}
    }
    Note that graphicsFrameCount and logicFrameCount are incremented in their respective functions: RunLogic() and DrawObjects().

    Does this implementation seem solid to you guys or would you have any suggestions on things to fix or improve?
    My Website

    "Circular logic is good because it is."

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I wanted to make it so that everything gets drawn a fixed number of times per second, and so that the logic happens a fixed number of times per second, ...since that is the proper way to do things anyways..., and it makes the game less susceptible to differences in performance of two different computers.
    It is? The only time you would need to cap the framerate manually is if you had a physics system. Other than that vsync will cap it for you quite nicely. If you do have a physics system you must keep consistent deltas or your equations will get odd results.

    Just compute the frame delta and pass that into your update function to update your game world. Then draw.

    Code:
    ...
    QueryPerformanceCounter(&m_nowTime);
    float timeDelta = static_cast<float>(m_nowTime.QuadPart - m_lastTime.QuadPart) * (1.0f / m_perfFreq.QuadPart);
    ...
    InputControl->HandleInput();
    GameWorld->Update(timeDelta);
    GameWorld->Render();
    ...
    ...
    m_lastTime = n_nowTime;
    Last edited by VirtualAce; 07-25-2009 at 10:17 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Logic Problems
    By mike_g in forum C Programming
    Replies: 3
    Last Post: 08-06-2008, 10:19 AM
  2. God
    By datainjector in forum A Brief History of Cprogramming.com
    Replies: 746
    Last Post: 12-22-2002, 12:01 PM
  3. Logic of my for loops.
    By etnies in forum C Programming
    Replies: 3
    Last Post: 04-15-2002, 10:00 AM