Dynamic Spritesheet Loading

Does anyone have an idiom for loading spritesheets into memory on demand
and then unloading them?

I have LOTS of spritesheets (58 not counting other images for masks and errant ui items) and I’m worried about a phone’s ability to load them as part of the app, if they can be stuck in memory and swapped as needed.

Please supply a small bit of script showing how you load one and use it and we’ll give the appropriate feedback.

I’m asking for this because, I often see folks say ‘spritesheet’ when they mean ‘image sheet’.  Depending on how you are using the images in the sheet, the answer to your question will be slightly different.

-Ed

For a given scene:

local _IntroNfo = require(“images.sprites.intro”)

local _IntroSheet = graphics.newImageSheet( “images/sprites/intro.png”, _IntroNfo:getSheet() )

I remove them on destroyScene with:

unrequire(“images.sprites.intro”)

_IntroSheet = nil

This (in my testing) has led to no memory change after the scene is disposed, meaning no memleak. 

This is not my concern. My concern is that I load up to 8 at a time. I have characters and thumbnails and stylized “profile” images of almost 300 characters. Rather than expand the number of sheets that the app is loading, I would prefer some mechanism to pull a sheet remotely and load it as needed.

Thanks, now let’s see if I can help…

Freeing Memory

You’re doing pretty much the right thing to ensure cleanup:

  • Destroy all sprite objects you create. - I assume you’re doing this.
  • Make sure any handles used are nil. - I also assume you’re doing this.
  • unrequire() the sprite definition (“images.sprites.intro” in the sample above).
  • nil the handle referring to the image sheet.

After this, the memory (main and video) will be freed automatically if it is needed.

So far so good.

Measuring Memory

Beware absolutes when measuring memory usage.  It is normal for main memory usage to go up and not come back down.  This does not imply there is a leak unless the increase continues without end.  Rather, this is simply a side-effect of how Lua manages main memory.  Likewise measuring video memory usage is a tricky thing.  The hardware won’t free video memory right away unless it needs to AND the memory is not in use.  (You’re already ensuring this.)

I’m merely giving you this warning so you don’t think a increase is a leak.  Only unbounded and continuous increases should be worried about.

Maximum Simultaneous In-Use Sheets

RE: Loading X at a time.   X in this case is ‘8’.

Here is where trouble can begin.  In my experience and as I understand the functionality of hardware.  There is a hard limit to the number of image sheets that can be loaded and retained in memory at any time.  This is dependent upon the amount of dedicated video memory.  (Someone else may be able to explain this better than I).  My only advice here is that you try to keep the number of simultaneously in use sheets as low as possible.  Otherwise you’ll find certain devices simply cannot handle your app/game.

Remote?

You lost me on this last bit.  Are you saying you want to deliver your app with a small set of sheets and download more?  I think the answer is no, because it doesn’t seem to fit your original question.  However, I can’t quite grasp what you mean by ‘remote’ if that isn’t it.

Please clarify on your use of the word ‘remote’.

Meanwhile, sorry for the long answer, but I hope it helps a little.

These explanations are helpful, as I’ve had to test-and-guess most of it.

To clarify “remote”, if I have a mobile corona application running in a phone and an endpoint exists… http://server.com/spritesheets?id=112 that can serve up an image file, is there a clean way to request it from the endpoint, load it in a scene, use it in a scene, dispose of it (repeat)? I’m currently only using image files that are compiled in to the app (50ish) and it’s already hefty. In the future, I can imagine additional sheets being needed.

Sure.

You can download the image to the Temporary folder.  Use it like you normally would, then later when it is no longer in use, the OS will eventually remove it.

The tricky part will be assembling the sprite definition.  While you can’t download and run LUA files, you can code up a module that generates sprite definitions (the code that identifies where images live in the sheet).  (I am probably not using the right term here, sorry.)

Hmm…

I’m sure I answered a question like this earlier this year or late last year.  Let me dig around for it.  (It may have been tagged in one of the “From The Forums” blog posts.)

I’ll ping back if I find it or not, either way.

Found it.  Hopefully this gets you started with the downloading.  It isn’t exactly what you need, but it can be modified to handle the download and response when the file arrives.

https://forums.coronalabs.com/topic/54861-return-loadremoteimage-from-url-or-load-locally-if-exists/

You can also download to the documents folder if you want to keep the image forever.

If you’re really taking this to the next level, you may need a way to identify the names of remote files.  You can do this by communicating with your server and asking for file names based on GET queries.  There was article recently on this kind of coding here:

(Written by the Rob meister I believe)

https://coronalabs.com/blog/2015/06/02/tutorial-connecting-to-restful-api-services/

Please supply a small bit of script showing how you load one and use it and we’ll give the appropriate feedback.

I’m asking for this because, I often see folks say ‘spritesheet’ when they mean ‘image sheet’.  Depending on how you are using the images in the sheet, the answer to your question will be slightly different.

-Ed

For a given scene:

local _IntroNfo = require(“images.sprites.intro”)

local _IntroSheet = graphics.newImageSheet( “images/sprites/intro.png”, _IntroNfo:getSheet() )

I remove them on destroyScene with:

unrequire(“images.sprites.intro”)

_IntroSheet = nil

This (in my testing) has led to no memory change after the scene is disposed, meaning no memleak. 

This is not my concern. My concern is that I load up to 8 at a time. I have characters and thumbnails and stylized “profile” images of almost 300 characters. Rather than expand the number of sheets that the app is loading, I would prefer some mechanism to pull a sheet remotely and load it as needed.

Thanks, now let’s see if I can help…

Freeing Memory

You’re doing pretty much the right thing to ensure cleanup:

  • Destroy all sprite objects you create. - I assume you’re doing this.
  • Make sure any handles used are nil. - I also assume you’re doing this.
  • unrequire() the sprite definition (“images.sprites.intro” in the sample above).
  • nil the handle referring to the image sheet.

After this, the memory (main and video) will be freed automatically if it is needed.

So far so good.

Measuring Memory

Beware absolutes when measuring memory usage.  It is normal for main memory usage to go up and not come back down.  This does not imply there is a leak unless the increase continues without end.  Rather, this is simply a side-effect of how Lua manages main memory.  Likewise measuring video memory usage is a tricky thing.  The hardware won’t free video memory right away unless it needs to AND the memory is not in use.  (You’re already ensuring this.)

I’m merely giving you this warning so you don’t think a increase is a leak.  Only unbounded and continuous increases should be worried about.

Maximum Simultaneous In-Use Sheets

RE: Loading X at a time.   X in this case is ‘8’.

Here is where trouble can begin.  In my experience and as I understand the functionality of hardware.  There is a hard limit to the number of image sheets that can be loaded and retained in memory at any time.  This is dependent upon the amount of dedicated video memory.  (Someone else may be able to explain this better than I).  My only advice here is that you try to keep the number of simultaneously in use sheets as low as possible.  Otherwise you’ll find certain devices simply cannot handle your app/game.

Remote?

You lost me on this last bit.  Are you saying you want to deliver your app with a small set of sheets and download more?  I think the answer is no, because it doesn’t seem to fit your original question.  However, I can’t quite grasp what you mean by ‘remote’ if that isn’t it.

Please clarify on your use of the word ‘remote’.

Meanwhile, sorry for the long answer, but I hope it helps a little.

These explanations are helpful, as I’ve had to test-and-guess most of it.

To clarify “remote”, if I have a mobile corona application running in a phone and an endpoint exists… http://server.com/spritesheets?id=112 that can serve up an image file, is there a clean way to request it from the endpoint, load it in a scene, use it in a scene, dispose of it (repeat)? I’m currently only using image files that are compiled in to the app (50ish) and it’s already hefty. In the future, I can imagine additional sheets being needed.

Sure.

You can download the image to the Temporary folder.  Use it like you normally would, then later when it is no longer in use, the OS will eventually remove it.

The tricky part will be assembling the sprite definition.  While you can’t download and run LUA files, you can code up a module that generates sprite definitions (the code that identifies where images live in the sheet).  (I am probably not using the right term here, sorry.)

Hmm…

I’m sure I answered a question like this earlier this year or late last year.  Let me dig around for it.  (It may have been tagged in one of the “From The Forums” blog posts.)

I’ll ping back if I find it or not, either way.

Found it.  Hopefully this gets you started with the downloading.  It isn’t exactly what you need, but it can be modified to handle the download and response when the file arrives.

https://forums.coronalabs.com/topic/54861-return-loadremoteimage-from-url-or-load-locally-if-exists/

You can also download to the documents folder if you want to keep the image forever.

If you’re really taking this to the next level, you may need a way to identify the names of remote files.  You can do this by communicating with your server and asking for file names based on GET queries.  There was article recently on this kind of coding here:

(Written by the Rob meister I believe)

https://coronalabs.com/blog/2015/06/02/tutorial-connecting-to-restful-api-services/