Implementing Unload_fpg In A Good Way


Burbruee

Member
Joined
Sep 28, 2006
Messages
302
Location
Skåne, Sweden.
Website
Visit site
In my game, I have animated backgrounds of 32 frames that are repeating themselves over and over.
There are 10 levels, each with a new animated bg.

I have stored the bg frames for each level in a separate fpg, each fpg are about 2.5 MB in size if you compress them, otherwise 5 MB.

It works fine on the PC, a black screen for maybe 1 second and then the game will proceed.
On the GP2X, I must comment out the load_fpg section for levels over 3.
Even then, the game takes a while to load, if I put in the animated background for a fourth level, the game won't even start. Stays black for maybe 15 seconds and then it goes back to the menu.

This is okay, because of the way I have currently programmed it, it tried to load all fpgs upon boot. (roughly 25 MB if compressed)

Now, the way it works at the moment. It's a puzzle game, and for each 100 levels the background should change.

To optimize, I would like it to unload the previous fpg before the new background loads.
I'm having trouble implementing this.

Here's a code snippet from the bg() process:

CODE

PROCESS bg( x, y )
BEGIN
file = bg[0];
graph = 1;
z = 100;

bg[0] = load_fpg( "data/graphics/level0.fpg" );
bg[1] = load_fpg( "data/graphics/level1.fpg" );
bg[2] = load_fpg( "data/graphics/level2.fpg" );
bg[3] = load_fpg( "data/graphics/level3.fpg" );
bg[4] = load_fpg( "data/graphics/level4.fpg" );
bg[5] = load_fpg( "data/graphics/level5.fpg" );
bg[6] = load_fpg( "data/graphics/level6.fpg" );
bg[7] = load_fpg( "data/graphics/level7.fpg" );
bg[8] = load_fpg( "data/graphics/level8.fpg" );
bg[9] = load_fpg( "data/graphics/level9.fpg" );

loop;
graph++;

//maybe I could have used a for here for all this.. but I was very tired
if( curLvl >= 0 )
file = bg[0];
end;
if( curLvl >= 100 )
file = bg[1];
end;
if( curLvl >= 200 )
file = bg[2];
end;
if( curLvl >= 300 )
file = bg[3];
end;
if( curLvl >= 400 )
file = bg[4];
end;
if( curLvl >= 500 )
file = bg[5];
end;
if( curLvl >= 600 )
file = bg[6];
end;
if( curLvl >= 700 )
file = bg[7];
end;
if( curLvl >= 800 )
file = bg[8];
end;
if( curLvl >= 900 )
file = bg[9];
end;
frame(250);
end;
END


You can see why things are going bad right? Loading that much data at once... On the GP2X it's too much it seems.
What I would like to do is, in each of those ifs, unload the current and load the next, or something like it.
But.. Everything is in a loop. So it would be executed forever. Loading each fpg an unlimited amount of times. :rolleyes:

So, how can I best solve this?

Thanks.
 
Last edited by a moderator:
'Burbruee' said:
I have stored the bg frames for each level in a separate fpg, each fpg are about 2.5 MB in size if you compress them, otherwise 5 MB.
Use a different file format or shrink the files. Seriously, the GP2X is 320x240x(something less than 24-bit), so anything else is overkill and just wasted. Even as a uncompressed bitmap, that's only 76,800 pixels and with 24-bit colour, that would be three bytes per pixel - giving a MAXIMUM size of 230Kb. What the hell are you doing to get 5Mb PER FRAME? I don't know what format fpg is (vector, scalar?) but ffs... it's something like 10-20 times worse than storing an uncompressed bitmap of the maximum GP2X screen size in memory.

Even if you "pre-render" those fpg's once and just get a 320x240 bitmap for each frame of your background animation, that's only 230Kb x 32 frames = 7Mb uncompressed in total.

Trying to on-the-fly decompress a 5Mb file to the screen 32 times is a heck of a lot of work for the GP2X to do in realtime... not even processing or RAM, but the sheer bandwidth that takes up is enough to kill your program.

If you were to just draw those 32 frames once onto an SDL_Surface each, for instance, and store those 32 SDL_Surface's in RAM and just blit them one after another you would save, what, dozens of Megabytes of data transfer with each loop? And the changeover would be near instantaneous... trying to real-time decompress, interpret and draw a frame form a disk file is just stupid for something like that - imagine the work that the SD card is doing for a start (because there would be zero buffer RAM left to do anything like cache the original files).

Ledow's first rule of programming: Always program on a machine as powerful as, or less powerful than, the target device... then you realise that you have to optimise AS YOU PROGRAM rather than after you'd produced a shiny program that runs nicely on your Dual-Core 3GHz.
 
Last edited by a moderator:
No offense ledow but what you've just said is pointless as you've missunderstood the question and I'm guessing have no working knowledge of fenix so disregard that answer Burbruee.

For the benefit of those who don't know an fpg is a library of several images of either 16bit or 8bit, it also has the option to be further compressed. The problem Burbruee has is that he has 10 such fpg each containing 32 images for a total of 320 fullscreen bitmaps. This is obviously too much for the gp2x to handle in one go.

Right, now to solutions. First there would be no need to have this bg process running in a loop, you only need to call this process at the begining of the level (or in your case every 100 levels) and you don't need a different variable for each level pack, just use 'bg' as the holder for all level packs. Then when the level finishes and you main game loop ends you unload_fpg(bg), it should then go back to the beginning of the main loop and launch the 'bg process' to load the new fpg for the next level. This way you only ever have one bg fpg in memory. Personally I would simplify this even further though and scrap the bg process and incorporate it into the main loop, below is how I would go about it - not in real code but should give you an idea of how to go about it.


CODE

Process main_game()

BEGIN

LOOP - main loop

bg=load_fpg("current level.fpg") - you need to have a section of code to load the correct fpg for the level here.

REPEAT - start of game loop

** main game code here **

UNTIL(level is complete) - main loop ends when your requirement are met.

UNLOAD(bg) - unloads the fpg

END - end of main loop so it returns to the loop command and executes you code to load the next level bg.

END - end of process



I hope that gives you the idea but if you need more help you can PM me and maybe chat on MSN to help sort out any problems you might have.
 
Last edited by a moderator:
If you have fpg's which are 5MB uncompressed then that is the size they will be when the GP2x loads them (I am pretty sure it decompresses them on load). This means that you are maybe running out of ram.
 
Last edited by a moderator:
Back
Top