How to load a lot of images or spritesheets efficiently?

I am recreating an old game that was created in the late 90’s (I’ve received permission to use the game images). The game has about 6000 100x100 images, which are mostly character frames for animation. The game (C++) was able to load the images and keep memory usage for the entire game around 50,000K. I know that the original game stored all the bitmaps in a special MultiBitMap format.

I am willing to change the images’ format to any format. I just want to get memory usage down significantly. I tried creating 15 (2048x2048, with transparency) PNG spritesheets, and then loading them using the Slick 2D game library, however, memory usage went through the roof. I thought about making smaller spritesheets, and loading just the sheets I need for the scene, however, it’s possible the a single scene would need all the spritesheets loaded to render the scene. I am even considering the DDS file format…

Any suggestions?

Thank you

My understanding is that Slick2D creates multiple copies of the image data. If you’re only using Slick2D for the texture loading, you might want to write your own texture loading code, that doesn’t make any copies and doesn’t keep it all in RAM, after it has been sent to the GPU.

BTW: 6000 x 100x100 PNG = 6000 x 100x100x4 = 240000000 bytes (228MB)

I’ll give that a try. Thank you for your help.

I found a great solution for myself!

I just used java.awt.Image (ImageIO.read) and created a class to store every tile information (6000 of them) with a cache expiration time property, Image property, etc. When a file needs to be drawn, it checks if it’s loaded, if not, it loads it. Then it updates the cache expire time plus one second, and finally draws. At the end of every scene, I expire unused tiles. My memory use is at 40,000K and my CPU is VERY low too. This works great for me, but I bet it wouldn’t work in a lot of other situations.

There are some very efficient loaders in TWL and exist as an independent package if you need it. They load png and jpg directly into a byte buffer.

Thank you. I’m going to look into it right now.

ImageIO is an OK solution if you just want something quick and easy. For better efficiency, here is what I would recommend:

[]Determine a way to only store what sprites are necessary in memory. This might involve extending Image with custom timers and an “expiration time.” Or this may be “zone-based” (i.e. if the player exits the snow level, you can destroy the snow tiles…).
[
]Allocate some empty textures – how many depends on how much memory you want to allot to texture data, and how many sprites will be needed in memory at once. (Sounds effects also tend to take up a lot of memory.)
[]When the textures are needed (e.g. user enters snow level) then decode the sprite using PNGDecoder (or another of Matthias’ decoders) and upload the byte buffer to one of your textures using glTexSubImage2D or a utility like this (note: if you use my PixelData utility, you’ll want to add your own methods to deal more directly with the byte buffer).
[
]Ideally threading would be used to load data in the background, as to not hog the CPU

This technique has the downside of being rather complicated. Truth is, your game probably doesn’t require a very complex system like this. Most games that require thousands of sprites do not require them all to be rendered at the same time, and so it would be better to design a simple loading/unloading system based on levels or zones. You can use Image() to load the image, and destroy() to unload the image. Or you can just stick to ImageIO, which seems to be working for your needs. :slight_smile:

Wonderful suggestions. :slight_smile:

My game has no levels. Nearly all my sprites are apart of character animations. I removed a signification amount of sprites, which I didn’t really need. I went from about 6000 to 3600. Everything is rendering smoothly.