Game Development Community

Animated Loading Screens?

by Sean Dugan · in Torque Game Builder · 08/13/2007 (2:44 pm) · 2 replies

Though this would not be absolutely necessary to our project, it would be of great benefit to us if we could find a way to play animations while resources are loading. Currently, when we load external resources, all animations stop and the game appears to have locked up. One problem we have is that many things have seemingly excessive load times, and these animations stopping can cause the player to believe the game is no longer functioning. While we hope to fix these problems in the future, such a loading screen would still be beneficial with any wait time.

If this is possible, it would also be helpful if someone knew a way to track the progress of a block of resources. It would be extremely simple to create a progress bar or other indicator with such data, and would let the user know that the program is still working.

Thanks.

#1
08/14/2007 (6:53 am)
I'm still new to TorqueScript and TGB, but i don't think they support spawning threads which at first glance seems what you would need for that. That way you could have animations running independent of the resource loading.
However if you DID figure it out then that would rock. Ratchet & Clank is a good example of drawing attention away from loading screens :)
#2
08/16/2007 (2:38 pm)
Here's a "better than nothing" all-script solution. Break down resource .cs files into smaller sets into multiple .cs files and write 'file queue' functions that exec one file and then relinuqishes control back to the renderer for a few hundred milliseconds between.

Here's a bare-bones example which should work (barring any syntax errors/typos):

function initFileQueue(%progressCallback, %finishCallback)
{
   $fileQueue::progressCallback = %progressCallback;
   $fileQueue::finishCallback = %finishCallback;
   $fileQueue::totalFilesQueued = 0;
   $fileQueue::totalFilesExeced = 0;
   $fileQueue::queuedFileCount = 0;
}

function queueFile(%filename)
{
   if ($fileQueue::queuedFileCount $= "")
   {
      $fileQueue::queuedFileCount = 0;
   }

   $fileQueue::queuedFile[$fileQueue::queuedFileCount] = %filename;
   $fileQueue::queuedFileCount++;
   $fileQueue::totalFilesQueued++;
}

function processFileQueue(%timeDelay, %batchExecQty)
{
   if (%timeDelay $= "")
   {
      %timeDelay = 200;
   }

   if (%batchExecQty $= "")
   {
      %batchExecQty = 1;
   }

   for (%iii = 0; %iii < %batchExecQty && $fileQueue::queuedFileCount > 0; %iii++)
   {
      exec($fileQueue::queuedFile[0]);

      $fileQueue::totalFilesExeced++;

      if ($fileQueue::totalFilesQueued > 0)
      {
         if ($fileQueue::progressCallback !$= "")
         {
            call($fileQueue::progressCallback, $fileQueue::totalFilesExeced / $fileQueue::totalFilesQueued);
         }
         Canvas.repaint();
      }

      for (%jjj = 1; %jjj < $fileQueue::queuedFileCount; %jjj++)
      {
         $fileQueue::queuedFile[%jjj - 1] = $fileQueue::queuedFile[%jjj]; 
      }
   
      $fileQueue::queuedFileCount--;
   }

   if ($fileQueue::queuedFileCount > 0)
   {
      schedule(%timeDelay, 0, "processFileQueue", %timeDelay, %batchExecQty);
   }
   else
   {
      if ($fileQueue::finishCallback !$= "")
      {
         call($fileQueue::finishCallback);
      }
   }
}

To use: Initialize the queue by calling initFileQueue with two optional parameters which are callbacks to your own code. The first is a progress callback which will get called every time one file gets exec'd. This callback gets a float value passed to it between 0.0 and 1.0 representing the percent of the queue that has been processed. The second callback happens when the queue finishes.

Next, instead of calling exec() directly, call queueFile() repeatedly with the list of resource .cs files. Make sure to take big .cs files that have lots of resources (with preloaded images/sounds) and split them out; the smaller each .cs file the smoother the loading behavior will be. An extreme example would be to put each imageMap or AudioProfile definition into it's own file, but that granularity is not usually necessary.

When all files are added to the queue, call 'processFileQueue' with two optional values. The first specifies how long to 'pause' between exec's (giving time back to other functions and the renderer) and the second is how many files to exec per pass. Both params have defaults that work fairly well (200ms and 1 file at a time). Be aware that if you set the pause time too low there can be bizarre side effects, as the schedules pile up when an exec takes longer than your scheduled pause length.

With these functions, a decent progress bar implementation can be done. The biggest downside is that you're actually increasing the time it takes to load the resources (adding that 'pause' time for each file in the queue), but having a progress bar or at least an animated icon is usually worth it. This really should be implemented in the engine code itself too, where a whole bunch of smarter things could be done.