Custom render loop

So you’re in need of more control over the idle loop, but Gorgon keeps taking all the power away from you? Well fear not, there’s a way to bypass Gorgon’s internal render loop and use your own.

Initialize

Let’s look at and modify the Initalize example. First let’s review the current (and standard) setup:

This is our idle function. This gets called while the system is in an idle state (i.e. no messages to process).

/// <summary>
/// Handles the OnFrameBegin event of the Screen control.
/// </summary>
/// <param name=sender>The source of the event.</param>
/// <param name=e>The <see cref="GorgonLibrary.FrameEventArgs"></see> instance containing the event data.</param>
private void Screen_OnFrameBegin(object sender, FrameEventArgs e)
{
   // Clear the screen.
   Gorgon.Screen.Clear();
}

And this, obviously, is our initialization code. We’re only interested in 2 lines here.

/// <summary>
/// Handles the Load event of the MainForm control.
/// </summary>
/// <param name=sender>The source of the event.</param>
/// <param name=e>The <see cref="System.EventArgs"></see> instance containing the event data.</param>
private void MainForm_Load(object sender, EventArgs e)
{
   try
   {
      // Initialize the library.
      Gorgon.Initialize();

      // Display the logo and frame stats.
      Gorgon.LogoVisible = true;
      Gorgon.FrameStatsVisible = false;

      // Set the video mode to match the form client area.
      Gorgon.SetMode(this);

      // Assign rendering event handler.
      Gorgon.Idle += new FrameEventHandler(Screen_OnFrameBegin);

      // Set the clear color to something ugly.
      Gorgon.Screen.BackgroundColor = Color.FromArgb(250, 245, 220);

      // Begin execution.
      Gorgon.Go();
   }
   catch (Exception ex)
   {
      UI.ErrorBox(this, "An unhandled error occured during execution, the program will now close.", ex.Message 
                  + "\n\n" + ex.StackTrace);
      Application.Exit();
   }
}

My way or the highway

So how do we get this rendering in your own custom loop? Let’s modify the above code. First off, let’s get rid of the Screen_OnFrameBegin() function and replace it with:

public void MyLoop()
{
   // Let's clear the screen to purple.
   Gorgon.Screen.Clear(Color.Purple);
}

Now with that done, we need to bypass Gorgon’s render loop. This is accomplished by modifying the initialization code. We need to remove the following two lines:

// Assign rendering event handler.
Gorgon.Idle += new FrameEventHandler(Screen_OnFrameBegin);

// Begin execution.
Gorgon.Go();

These set up the internal render loop used by Gorgon. We need to replace it with this:

int startTick = Environment.TickCount;

while(this.Created)
{
   // We MUST call this, otherwise funky things will happen.
   // You could always import the Win32 API call PeekMessage and
   // perform your own message processing here.  That would help
   // determine if an app is idle.
   Gorgon.ProcessMessages();

   // Call our render loop every 5 seconds.
   if ((Environment.TickCount - startTick) > 5000)
   {
      MyLoop();
      startTick = Environment.TickCount;

      // This will perform the flip from the back buffer to the front 
      // buffer so that we can see our drawing.
      Gorgon.Screen.Update();
   }
}

So with this, admittedly dumb, example we can delay rendering every 5 seconds. Of course we can perform much more complex scenarios like rendering only once or rendering on command or after a state change.

Caveat Emptor

Since you’re taking away control from Gorgon, you will lose out on some functionality. For example, determining if your application is Idle and the timing data. All of that will now be up to the developer to implement. Also keep in mind that since the timing data will not be updated, the internal frame statistics code will not return valid data. Again, this is up to the developer to implement.

One thought on “Custom render loop

  1. GeorgZ

    You can restore the ability to get timing data by wrapping the meat of your game loop with a call to

    if ( Gorgon.FrameStats.Update())
                {
    ...
    }
    }

    as long as you set the framerate limiter to 0 to avoid gorgon messing up your own timings.

Leave a Reply