Pre-Loading Sprites/Heavy View Animations Into Memory **SOLVED**

Started by Knox, Thu 23/06/2011 17:01:32

Previous topic - Next topic

Knox

I found a relatively old thread about pre-loading sprites into memory: http://www.adventuregamestudio.co.uk/yabb/index.php?topic=39487.0

I was wondering, how can I pre-load all the game sprites efficiently the moment the player presses either the "start new game" or "continue game" button from the main menu?

GarageGothic suggests in the thread posted above:
QuoteYou could play the animation on an invisible object first, then the sprites should be preloaded in memory for when you actually need them.  

Is this a good way to do it? Or is there a better way? I have some very heavy animations for some full-screen effects (1024x768) and the firt time around, those animations lag...but once they've been played once + loaded, they run quite smoothly.

I'd add a  "loading bar" aswell to show the progress of each sprite/animation views being loaded into memory...so that way the player only needs to load everything once, at the beginning.

Im sure its doable, only Im not too sure how, or the best way to load them without the player seeing anything. I think* I can figure out the loading bar myself though...we'll see!
:P
--All that is necessary for evil to triumph is for good men to do nothing.

mode7

If you really want to preload all of the sprites into memory you could do this by creating an dynamic sprite array. I'm doing this for my tile engine.
However this would mean loosing most of AGS functionality e.g. the Animate function. You could code your own of course but this is probably not really a practical solution.

Did you try GarageGothic suggestion yet? does it work?

Knox

Hi mode7!

Hmm, well I dont think I would want to lose the functions, like Animate, haha! Is there a way to create a dynamic sprite array without losing the built-in functions?

I'll continue checking the various threads/help manual and try to find some obscure solution hidden away somewhere...if I find something I'll post it here.

The 1st time I tried GarageGothic's solution was quite a while ago, and I didnt get positive results...however I think I'll regive it a go and see what I come up with.
--All that is necessary for evil to triumph is for good men to do nothing.

mode7

Well you could load all the sprites into memory usingt a dynamic sprite but AGS will probably load them again when drawing chars or object. Anyway you could try it of course. Just do this before you animate and see if it works
Code: ags

// room script file
ViewFrame *SpritesData[3000];
DynamicSprite *Sprites[]; 
 
function room_AfterFadeIn()
{

int spritescount;
int v = 1;
while (v < Game.ViewCount+1)
{
  int l;
  while (l < Game.GetLoopCountForView(v))
  {
    int f;
    while (f < Game.GetFrameCountForLoop(v, l))
    {
      SpritesData[spritescount] = Game.GetViewFrame(v, l, f);
      f++;
      spritescount++;
    }
    l++;
  }
  v++;
}
Display("%d sprites written", spritescount);
 
Sprites = new DynamicSprite[spritescount];
int s;
while (s < spritescount) 
{
  Sprites[s] = DynamicSprite.CreateFromExistingSprite(SpritesData[s].Graphic, true);
  s++;
}
Display ("%d dynamic sprites precached",s);
 
}


This will load all your sprites which have been assigned to views into memory (well only the first 3000 of them - this is an arbitrary number and if you have more it will probably crash).
However these are loaded into a dynamic sprites so I dont think it will actually affect other instances. Try it anyway

Knox

Ok, Ill try that tonight and post the results here. I currently have around 3800 sprites, so Ill test it to see if I can change the number in your script to that amount.

Thnx for the help mode7, its appreciated!
--All that is necessary for evil to triumph is for good men to do nothing.

Knox

#5
ok, well I got it all setup, however I am getting a crash error due to the number of sprites in "ViewFrame *SpritesData[3000]"

Error running function 'room_AfterFadeIn': Array index out of bounds (index: 3000, bounds: 0..2999)

**ps: I currently have 3436 sprites.

**EDIT: I did GarageGothic's method. I set the object's transparency to 100 to make it invisible and assigned+animated (one by one)  the heavy views after the room loads...all of them eBlock (so each one plays fully one after the other). It seems to me (unless Im wrong) that there isnt any noticeable speed improvement after those animations have been played on that invisible object.
--All that is necessary for evil to triumph is for good men to do nothing.

Mazoliin

As mode7 said:
Quote
This will load all your sprites which have been assigned to views into memory (well only the first 3000 of them - this is an arbitrary number and if you have more it will probably crash).
However these are loaded into a dynamic sprites so I dont think it will actually affect other instances. Try it anyway

So just increase the array limit to a minimum of 3436. And make sure you call Delete() on all the dynamic sprites before quitting the game.

If just loading the frames to dynamic sprites doesn't help, you can overwrite the Graphic property of the ViewFrame* to point to the dynamic sprite. But be careful, this means you'll have to keep the sprite in memory as long as you want to be able use the views.

Knox

#7
@ Mazoliin: Oh I forgot to mention I did replace the number 3000 to 3436, but I made a typo, it was actually 3463...so that's why I was getting that error :P

Well we're almost there, it seems to run after the room load, just I get an out of memory error now right after this line is displayed-->Display("%d sprites written", spritescount);

Code: ags

Error: Out of memory: failed to allocate 2055200 bytes (at PP=6)
--All that is necessary for evil to triumph is for good men to do nothing.

Zetsaika

Did you tried to use more sprite cache on Advanced Options in the setup?
"In the longest day, in the shortest night. No Zombie shall escape my sight."

Knox

Hi Zetsaika,

Thats a good idea. I checked but its already set at the current maximum, 100mb.

Do you think we can change the maximum amount of the sprite cache to something much bigger than 100mb? (like a feature request?) If so, well I post in the appropriate thread!
--All that is necessary for evil to triumph is for good men to do nothing.

mode7

It has to do with the dynamic array I used. This should fix it.


Please note that this arrays will blow up your exe filesize (winzip will compress most of it though)

Code: ags

// room script file
ViewFrame *SpritesData[3500];
DynamicSprite *Sprites[3500]; 
 
function room_AfterFadeIn()
{

int spritescount;
int v = 1;
while (v < Game.ViewCount+1)
{
  int l;
  while (l < Game.GetLoopCountForView(v))
  {
    int f;
    while (f < Game.GetFrameCountForLoop(v, l))
    {
      SpritesData[spritescount] = Game.GetViewFrame(v, l, f);
      f++;
      spritescount++;
    }
    l++;
  }
  v++;
}
Display("%d sprites written", spritescount);
 
int s;
while (s < spritescount) 
{
  Sprites[s] = DynamicSprite.CreateFromExistingSprite(SpritesData[s].Graphic, true);
  s++;
}
Display ("%d dynamic sprites precached",s);
 
}

Knox

Hi mode7,

Ok well I tried the new version, still get that pesky memory error (but with a different number after the "PP" )-->

Code: ags
Error: Out of memory: failed to allocate 2055200 bytes (at PP=1101)

--All that is necessary for evil to triumph is for good men to do nothing.

mode7

Strange it works for me. Are your declarations for ViewFrame and DynamicSprite outside of the After Fadein Loop?

Knox

#13
Exactly as shown.

I did some further tests and noticed it works for me only if I select in the setup settings "downgrade 32-bit to 16-bit".

**EDIT: So I guess this doesnt work for 32-bit alpha sprites?
--All that is necessary for evil to triumph is for good men to do nothing.

Knox

Ok well I decided to pre-load my sprites onto a "gLoadSprites" gui instead...and it works better than if it was on an object (plus I can place that gui in any room I want/creating it only once + setting its transparency to 100).

Ill let the other solutions go for now.

Thanks for your help!!
--All that is necessary for evil to triumph is for good men to do nothing.

SMF spam blocked by CleanTalk