How to do Loading Screens

Started by
24 comments, last by acid2 18 years, 10 months ago
Well can you use a singleton object that handles the menu loading and refreshing?

So inside your loading loop you update your loading bar by calling the singleton object. This method works best if you have a single progress bar and a total progress bar.

I have never done threads (haha I need to start learning lol) but I would think using two threads is the best way to go.


Advertisement
Quote:Original post by Vern777
Well can you use a singleton object that handles the menu loading and refreshing?


Why a singleton? A normal object works just as well (IMHO: alot better), there is absolutely nothing that the singleton will solve in this matter. The problem is to know how much you've loaded and how much is left, as well as render every once in a while.

I think that threads are the way to go if you need max fps update on the loading bar, just poll the loading thread on how far it's gotten every time you render. A more "jumping" loading bar animation could be done while loading. Just render after each loaded object. Heck, you can even use that to get the filename before loading so you can have "Loading: SingletonsOhTehNoes.omg..." etc.

What I can't really figure out is, how do you know how much is left? Do you insert some extra info in the beginning of the main load file or do you go through the list of all things that need to be loaded, or how do you guys do it?
[ ThumbView: Adds thumbnail support for DDS, PCX, TGA and 16 other imagetypes for Windows XP Explorer. ] [ Chocolate peanuts: Brazilian recipe for home made chocolate covered peanuts. Pure coding pleasure. ]
I posted without much thinking.

But my idea is that you may have different loading code so you can call the singleton object from anywhere. But usually all your loading code belong in the same place...

So you have a loop, you know how many times to loop perhaps, or you know how many vertices you need to load, that would figure into you percentage equation...





Rant! hehe I made it small so you can ignore it:
The singleton is the most misunderstood and missused pattern of all, it has become a "argh I'm to tired to design, let's just make this work!" pattern suddenly. It holds no advantage over being passed around like any other object you need to use. Unless you're force fitting it into something who's architecture / interface you can't / don't want to affect to much. Thus sneaking in a black-box communication system that there is no indication of that's it being used. To give an example of what I mean:

scene.load( filename ); VS scene.load( filename, loadingBar );

Which one uses the singleton (i.e. which one doesn't hint about using a loading bar?) and which one shows not just to the caller but the implementor of scene.load() that there's a loading bar and it should be used?

I've been thinking about "how do you know how big a step is?". Clearly there are differences in loading times, even for the same object made twice in a row or on two different computers (as pointed out by other posters). So there isn't even a point trying to make one object "worth more" than another. But if we (say 3D game) count triangles or models, when saving the game map this data is saved in a header part (i.e. in the beginning). Then you'd know how much to step after each modell. Other resources like sound and textures has to be taken into account too, of course. Easiest might just be having a "Total resources: 432" in the beginning and a small texture counts as much as a complex model. As mentioned earlier, we've almost come to expect jerky loading bars :)

I'm just speculating here. Has anyone tried this approach?
[ ThumbView: Adds thumbnail support for DDS, PCX, TGA and 16 other imagetypes for Windows XP Explorer. ] [ Chocolate peanuts: Brazilian recipe for home made chocolate covered peanuts. Pure coding pleasure. ]
Here is one approach you can try to make a smooth progress bar.

You need to know a few things about the machine that your app is running on:
1. The amount of data that you are going to be loading, in bytes for example
2. The spead at which your machine is loading that data (eg. bytes per millisecond)
3. A timer source (eg. in milliseconds)

The gist of this is to do an animation of the progress bar by calculating, on the fly, the spead at which the data is loading.

You can load the first chunk of data and figure out how long it took, and how many bytes were loaded. From this you can calculate the spead (bytes per millisecond, or what ever units you like).

Now that you know the spead at which your data is loading, you can do two things. If you assume that the rest of the data will load with a similar speed, then you can use the calculated spead to animate the progress bar. If not, then you can redo this calculation after each chunk of data is loaded.

To animate the progress bar, you smoothly interpolate it based on how much calculated time is left to load the remainder of the data.

If the platform that you are running your app on blocks during disk IO then you can either take the approach of using theads, or you can try to load data a byte or a few bytes at a time, do your progress bar calculations, and then continue on in a loop. If you write some library routines for doing your disk IO, then try incorporating this sort of progress bar functionality, and perhaps make it configurable for the times when you don't want the overhead of this kind of functionality.


Terry
Quote:Original post by Seriema
Rant! hehe I made it small so you can ignore it:
The singleton is the most misunderstood and missused pattern of all, it has become a "argh I'm to tired to design, let's just make this work!" pattern suddenly. It holds no advantage over being passed around like any other object you need to use. Unless you're force fitting it into something who's architecture / interface you can't / don't want to affect to much. Thus sneaking in a black-box communication system that there is no indication of that's it being used. To give an example of what I mean:

scene.load( filename ); VS scene.load( filename, loadingBar );

Which one uses the singleton (i.e. which one doesn't hint about using a loading bar?) and which one shows not just to the caller but the implementor of scene.load() that there's a loading bar and it should be used?

I've been thinking about "how do you know how big a step is?". Clearly there are differences in loading times, even for the same object made twice in a row or on two different computers (as pointed out by other posters). So there isn't even a point trying to make one object "worth more" than another. But if we (say 3D game) count triangles or models, when saving the game map this data is saved in a header part (i.e. in the beginning). Then you'd know how much to step after each modell. Other resources like sound and textures has to be taken into account too, of course. Easiest might just be having a "Total resources: 432" in the beginning and a small texture counts as much as a complex model. As mentioned earlier, we've almost come to expect jerky loading bars :)

I'm just speculating here. Has anyone tried this approach?


That's not what I meant.

What I wanted to do is to have a loading screen singleton... This has nothing to do with the actual loading.

If you have to refresh your screen while loading you need someway to refresh from inside you loading code. That's why it's best to use threads.

So at the beginning of loading some stuff I would do:

LoadScreen::getSingletonPtr()->start(totalNumOfItems);

for(int i = 0; i < totalNumOfItems; i++)
{

LoadScreen::getSingletonPtr()->setCurrentItem(i);
load(resource);


}


load(RESOURCE res)
{

//figure out how much each loop is worth in the total progress
//of this item pertange while. So if you have 100 vertes, 1 vert would
//be 1 % on the progress bar
LoadScreen::getSingletonPtr()->calPercentage();
for(int i = 0; i < numOfVerts; i++)
{

//load some verts
LoadScreen::getSingletonPtr()->updateCurrentItem(); //updates progress bar

}

}


just doing loadResource is trival..

What if I want to traverse a tree and update the progress of my tree traversal I would so something similar maybe.

I'm in no way an expert...
My prefered method is just to total up all the media im loading, then work out what each one is in terms of percetage. Pretty easy to do this with code to give it some dynamic quality. Then just load the files one by one, and update the Loader.Percent attribute of the loader class each time a file is loaded... then when the screen refreshes i.e.: Loader.Render() is called from your main loop, then it draws a nice up-to-date loading bar... so what if its jerky... if your loading more than 100 files, you'll prolly get a fairly even spread and then no one is gonna notice anyways ;-)

Hope this helps.
Steven ToveySPUify | Twitter
The other thing is that you don't have to do a percentage loaded kind of thing :- for example I have a suspicion that Quake doesn't do that. All the user is really interested in is that his computer hasn't crashed and that it is doing something normal (eg think of the busy cursor in most OS's [usually a sand timer]). For instance you can have an animation of some sort (say a spining hard-disk), and whilst you do that you can add messages about what you're doing ("Loading map...", "Loading textures...", "Loading models...", "Loading sounds..." etc.) [this incidentally gives you a bit of feedback when the user says 'it crashes in the load screen, blah blah blah']
Im kinda of partial to those loading messages, definately a good idea :-) Also as posted above is alot of help with debugging.
Steven ToveySPUify | Twitter

This topic is closed to new replies.

Advertisement