A while back I had made an example program in the GDK showing how some operations could be safely moved out of the drawing thread. Someone suggested, though I can't remember who off the top of my head, that a separate thread was used for loading media so that the program wouldn't hang while you did that. A year or so later, I finally decided to try it!
//This is a proof of concept for creating a load screen that operates in a different
//thread from the one that draws to the screen. This should allow the program to
//maintain a high framerate while loading. (DarkGDK typically halts to load media)
#include "DarkGDK.h"
#include <windows.h>
#include <process.h>
HANDLE loadInstance;
double loadPercentage=0.0;
char loadInfoOut[50]=" ";
class _loadBar{
public:
int x,y,w,h;
double percentage;
void set(int sx,int sy,int sw,int sh){
x=sx;y=sy;w=sw;h=sh;
percentage=0.0;
return;
}
void go(double inpercent){
percentage=inpercent;
dbInk(0xFFFFFF,0x000000);dbBox(x,y,x+w,y+h);
dbInk(0x000000,0x000000);dbBox(x+1,y+1,x+w-1,y+h-1);
dbInk(dbRGB(0,200,0),0x000000);dbBox(x+2,y+2,x+((w-2)*percentage/100),y+h-2);
return;
}
void go(void){
dbInk(0xFFFFFF,0x000000);dbBox(x,y,x+w,y+h);
dbInk(0x000000,0x000000);dbBox(x+1,y+1,x+w-1,y+h-1);
dbInk(dbRGB(0,200,0),0x000000);dbBox(x+2,y+2,x+((w-2)*percentage/100),y+h-2);
return;
}
};
void loadThread(void *pParams){
double total=241340.04;//Total file size in bytes divided by 100
//All our media should be loaded in this thread.
sprintf(loadInfoOut,"Loading...");
dbLoadImage("barnacles.BMP",1,1);loadPercentage+=dbFileSize("barnacles.BMP")/total;
dbLoadImage("brick1_T.BMP",2,1);loadPercentage+=dbFileSize("brick1_T.BMP")/total;
dbLoadImage("bunker.BMP",3,1);loadPercentage+=dbFileSize("bunker.BMP")/total;
dbLoadImage("Cement_render.BMP",4,1);loadPercentage+=dbFileSize("Cement_render.BMP")/total;
dbLoadImage("concrete_T.BMP",5,1);loadPercentage+=dbFileSize("concrete_T.BMP")/total;
dbLoadImage("cornice.BMP",6,1);loadPercentage+=dbFileSize("cornice.BMP")/total;
dbLoadImage("Dappled_fur.BMP",7,1);loadPercentage+=dbFileSize("Dappled_fur.BMP")/total;
dbLoadImage("door01.BMP",8,1);loadPercentage+=dbFileSize("door01.BMP")/total;
dbLoadImage("door02.BMP",9,1);loadPercentage+=dbFileSize("door02.BMP")/total;
dbLoadImage("flakeywall.BMP",10,1);loadPercentage+=dbFileSize("flakeywall.BMP")/total;
dbLoadImage("fur.BMP",11,1);loadPercentage+=dbFileSize("fur.BMP")/total;
dbLoadImage("georgian.BMP",12,1);loadPercentage+=dbFileSize("georgian.BMP")/total;
dbLoadImage("gothic_T.BMP",13,1);loadPercentage+=dbFileSize("gothic_T.BMP")/total;
dbLoadImage("Granite_chippings_T.BMP",14,1);loadPercentage+=dbFileSize("Granite_chippings_T.BMP")/total;
dbLoadImage("grass_T.BMP",15,1);loadPercentage+=dbFileSize("grass_T.BMP")/total;
dbLoadImage("lead.BMP",16,1);loadPercentage+=dbFileSize("lead.BMP")/total;
dbLoadImage("leaf.BMP",17,1);loadPercentage+=dbFileSize("leaf.BMP")/total;
dbLoadImage("Lichen_T.BMP",18,1);loadPercentage+=dbFileSize("Lichen_T.BMP")/total;
dbLoadImage("Metal_Plates_T.BMP",19,1);loadPercentage+=dbFileSize("Metal_Plates_T.BMP")/total;
dbLoadImage("metal_shutter.BMP",20,1);loadPercentage+=dbFileSize("metal_shutter.BMP")/total;
dbLoadImage("oak_door.BMP",21,1);loadPercentage+=dbFileSize("oak_door.BMP")/total;
dbLoadImage("oldmetal.BMP",22,1);loadPercentage+=dbFileSize("oldmetal.BMP")/total;
dbLoadImage("oldwood.BMP",23,1);loadPercentage+=dbFileSize("oldwood.BMP")/total;
dbLoadImage("Rocky_cliff_T.bmp",24,1);loadPercentage+=dbFileSize("Rocky_cliff_T.BMP")/total;
dbLoadImage("rustyIron.BMP",25,1);loadPercentage+=dbFileSize("rustyIron.BMP")/total;
dbLoadImage("Sandstone_cliff_T.BMP",26,1);loadPercentage+=dbFileSize("Sandstone_cliff_T.BMP")/total;
dbLoadImage("sandstone_T.BMP",27,1);loadPercentage+=dbFileSize("sandstone_T.BMP")/total;
dbLoadImage("SeaWeed.BMP",28,1);loadPercentage+=dbFileSize("SeaWeed.BMP")/total;
dbLoadImage("slimey.BMP",29,1);loadPercentage+=dbFileSize("slimey.BMP")/total;
dbLoadImage("Street_cabinet.BMP",30,1);loadPercentage+=dbFileSize("Street_cabinet.BMP")/total;
sprintf(loadInfoOut,"Done.");
return;
}
void DarkGDK(void){
char szTemp[50]=" ";
dbSetDisplayModeVSync(640,480,32,0);
dbSetWindowTitle("Loading Example");
_loadBar loadBar;loadBar.set(dbScreenWidth()/2-200,dbScreenHeight()/4*3,400,7);
loadInstance=CreateEvent(NULL,FALSE,FALSE,NULL); //Create the event for the load thread
_beginthread(loadThread,0,NULL);
while(LoopGDK()){
dbCLS();
dbCenterText(dbScreenWidth()/2,dbScreenHeight()/2-5,loadInfoOut);
sprintf(szTemp,"FPS: %d",dbScreenFPS());dbPrint(szTemp);
loadBar.go(loadPercentage);
dbSync();
}
for(int i=1;i<=30;i++){
dbCLS();
dbPasteImage(i,0,0,1);
dbSync();
Sleep(250);
dbDeleteImage(i);
}
return;
}
In order to run the example you'll have to copy all of the media from the included textures from ...\The Game Creators\Dark GDK\Media\Textures to your project directory (or drop the compiled EXE into that directory and run). When the load is finished the process safely terminates and the images can be used in your program! Watch the framerate carefully as it loads and you'll see that the rendering is being done at full speed despite loading that pile of pictures. And that's just 24 MB of information, imagine what could be done with more! You could provide your players with a mini-game while the main one loads (This is seen in retail games like Assassin's Creed 2, which has you fool around in a construct like level while the actual level loads).