# How to compress game frame by frame animation to a minimum on disk

I developing a game like Age of empire (buildings on map) and for every building I have a sprite sheet for its animation. I am using frame by frame animation to animate the building ( not aware of any other method anyways). I am noticing that my resources folder is going extremely large due to the images I am putting in it.

How do games like CoC and Age of Empires keep their apk size under 50 Mg? Am I missing something here when it comes to game development

Thank you

I have a LOT of animations drawables objects. I chose this way because it was the quickest and it was yielding the results the I want. Basically every building is an animation drawable in which its xml file refers to 8 drawables (8 images = 8 files). All of them are PNG due to transparency. Since I have over 200 images, the apk size is 120 MB ( And I am not done copying half of the files yet). That's what prompt, there has t o be a way to solve it. Please assist a fellow developer

• Compressing images or separating game content from the apk might be what you are looking for. – János Turánszki Nov 19 '15 at 16:07
• You mean expansion files? The problem that expansion files don't have the different density drawable folders. Is this what games do? I am doing frame by frame animation (full building image). Or am I totally in the wrong path – Snake Nov 19 '15 at 16:12
• Just in case, I tried to be of help and put an answer related to saving space for your images. However, your question is confusing: it's not clear whether you want to really know techniques like related to "how do games like CoC and Age of Empires keep their apk size under 50 Mg?" or if you wish to just check whether there are less disk-space hungry ways of animating (like your title suggests). Please clarify, so I can delete my answer if that's the case and also so you can get more accurate answers. – MAnd Nov 19 '15 at 17:16
• @MAnd I edited my answer to reflect on the problem further – Snake Nov 19 '15 at 21:20
• For Age of Empires, it's probably a combination of low resolution (IIRC it was designed for 640x480) and indexed images (not full RGB). – user253751 Nov 20 '15 at 0:14

It's not clear by your question if you really want to know techniques that allow games to save disk space even when having large amounts of heavy image/resource files (that's what is in the body of the question), or if you just wanna know if there are less disk-space hungry ways of doing animation for your buildings (that's what is implied by the title of your question).

So, I will put this answer here trying to be of help in relation to saving space when you have a lot of images. If you are only interested in knowing about animation techniques that might allow you to save disk space, please let me know then I might delete the answer.

That said, in a similar situation, two solutions I have seen (and used once) in terms of saving space in the disk, were:

1) to concatenate individual images within one same image. Sometimes it can be of help. So instead of saving 4 separate files for each of the following colored squares, I save all of them side-by-side within the same image (and will only split them via game code):

In this example, saving each in 4 different PNG files amounts to 1255 bytes, while the single file with all concatenated is 451 bytes. Of course, how much it could help depends on a case-by-case basis and you should test to see if that can be of help to you depending on your images.

2) to compress the resources folder. This can often be very helpful to save disk space. Then when the game is running you either decompress or pull the desired image from the compressed file - depending on the compression format you use. See this past answer that became a wiki of this site: https://gamedev.stackexchange.com/a/37649/72423

But also keep in mind that each type of compression may be more or less advantageous depending on the image file type you use: Avoid double compression of resources

For more details on compression: State of the art in image compression?

Lastly, you might also be interested in thinking which types of image to use for each situation: Which image format is more memory-efficient: PNG, JPEG, or GIF?

• Thank you for the information. It is weird you were able to cut the file size into half by putting things in one file. I thought at the end of the day, it is the same pixel count and space used . I edited my question for better answer – Snake Nov 19 '15 at 21:22
• @Snake So, per the edit you made, I think my answer can indeed be helpful. Concatenating images + compressing may reduce your folder size by a huge amount. Both techniques are regularly used in some types of games. About the concatenation, that's always a surprising trick. Try it yourself: put the images from a sequence of one animation of yours side-by-side and compare the final size with the sum of the individual images. Then you can see if that helps in your case. As for compression, for PNGs it tends to be less effective, but still worth the effort to cut size of your final folder – MAnd Nov 19 '15 at 21:32
• @Snake one observation, though: concatenating sometimes does not worth or even increases the final size a tiny bit. But oftentimes it can deliver desirable reduction. It all depends on your images – MAnd Nov 19 '15 at 21:41
• I remember trying both technique and the reduction was less than 10%. I definitely know compression does not matter with PNG but I will try the concatenation. That's why I asked how other games do it because obviously they have way more graphics than mine – Snake Nov 19 '15 at 21:45
• You shouldn't be able compress a folder full of images. The images should already be compressed, and should not have much repeatable sequences. If they did, that extra layer of compression would be part of the image codec... – corsiKa Nov 20 '15 at 19:26

I would propose that you try TexturePacker

• you can simply drag and drop all your images and get them packed
• you can apply different compression - e.g. use indexed PNGs which consume way less memory - up to 70% less compared to a standard PNG file
• you can create a file data files that contain the name + position of each of your buildings
• the free version might already suffice to create the sprite sheets for you

Do you use a game development framework like AndEngine, Cocos2d-x or LibGdx? => None

Do you need all your images loaded at the same time? It sounds like you'll run into massive RAM problems on the target devices.

Update: Snake sent me some images. As promised won't make them public here so I've created some art myself to demonstrate how to reduce the memory usage.

In the original image, only one part of the image was moving. I've placed a bird on a house to demonstrate this:

Basically packing the complete animation into a sheet is a big waste of memory. You should split static and moving parts:

Static:

Anim01:

Anim02:

Keep the original position of the bird in the images. This is why there is so mich empty space above. You need this for aligning the animation.

Now drag the images on TexturePacker and select the following parameters

• Data format: JSON hash (or XML if you prefer that)
• TrimMode: Trim (this creates rectangles)
• Pixel format: INDEXED 8bit - to create 8bit PNGs (about 70% less memory)
• Allow Rotation: false
• Enter a filename for the data

The result is that you now get 2 files: The sprite sheet and a JSON description file.

"house_anim_01.png":
{
"frame": {"x":351,"y":246,"w":110,"h":79},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":67,"y":8,"w":110,"h":79},
"sourceSize": {"w":400,"h":400},
"pivot": {"x":0.5,"y":0.5}
},


The important parts are frame and spriteSourceSize.

The frame gives you the location of the original sprite in the sprite sheet.

spriteSourceSize gives you the offset for drawing the image - the parts of the image that are left out because of the trimming:

A simple pseudo-code drawing routine looks like this:

drawImage(spritename, posX, posX)
{
data    = sheetData[spritename]
offsetX = data.spriteSourceSize.x
offsetY = data.spriteSourceSize.y
frameX  = data.frame.x
frameY  = data.frame.y
width   = data.frame.w
height  = data.frame.h
screen.draw(sheetImage, posX+offsetX, posY+offsetY, width, height)
}


You might have to adjust the offset calculation depending on the pivot point / origin in your graphics system. The routine above assumes a coordinate system who's origin is top left.

Then simply draw the house in 2 passes:

draw("background", 100, 100);
draw("anim_01", 100, 100);


You don't have to care about the offsets - since the images are already aligned.

• +1 for the observation about RAM use, which other people are ignoring – Dan Hulme Nov 20 '15 at 12:51
• @Andreas I will check that out. Thank you. Don't laugh at me but I am not using an engine. It is mostly done with animation and drawables and it working like a charm. I don't load all images in the memory no other wise it will crash. It just loads the images required for display at the moment.. do you think the above suggestion would work with standard Android SDK? – Snake Nov 20 '15 at 16:57
• Yes it will. TexturePacker has 2 modes for trimming sprites: Rectangles and polygons. If you use isometric images you might get a big advantage from polygon meshes in terms of packing. The question is if you would be able to draw textured triangles - or rectangles with a mask. If this is not the case you can still use the rectangles. You can send me some of your images if you want use dropbox and send a link to -> support at codeandweb . com . I won't share them - just interested to see what we can do to improve the packing. – Andreas Löw Nov 20 '15 at 20:12
• @AndreasLöw I am so sorry, I didnt get notification of your comment. I just saw it. I will very much appreciate the help. I will send you something and maybe you can shed light on what I should. ..kinda get stuck with something I have liittle experiece in and maybe you can shed light. I will contact you soon – Snake Nov 24 '15 at 4:02

Here are few pointer you can use

1. Try to make sure all your Background and non transparent images are not in PNG format
2. Try to have all animation loop-able i.e. if animation is 1,2,3,4,5,6 try to make it like 1,2,3,4,3,2,1 where these numbers are frame number of animation, it helps a lot
3. if many image are same and only color differs (generally UI buttons,m particle animations, game coins ) then try to take one White image and change its color dynamically
4. Try to make your .apk with only those images that are extremely important and then load everything from a server and keep in phone memory

I hope these pointers help

P.S. I am only give generalized idea as i am not aware of your exact game content and apologies if these pointers are not useful

• You can also: 1) compress all your images 2) use tiles as often as possible 3) concatinate images togetter into a larger image and use that as the uv map for texturing – Anthony Raimondo Nov 19 '15 at 16:36
• Those are great suggestions. Thank you. I think the most important point is 4. However if that's the case then how do I put them in the different drawable folders and reference them like R.drawable.image1 ? That's where I am confused – Snake Nov 19 '15 at 21:21

A lot of games don't keep their graphical assets in the .apk; they only include the "basics" like UI graphics and the game code and download the rest of the assets once the game's been installed. This is especially true for games that use different graphic resources depending on the resolution of your display to keep the .apk from having to contain both low-res and hi-res assets.

You should look at both the optimization options provided by the other answerers, as well as whether or not you will ultimately have to serve your game's graphics separately from the .apk itself.

• I have no issues getting the graphics from server ( or even expansion files), but how do I put them in drawable folder so I can reference them by R.drawable.x Since most of my (many many) xmls are referencing them using R.drawable – Snake Nov 19 '15 at 21:26
• AFAIK, you can't. One workaround is to keep a hash table of resource filenames linked to resource IDs, and use the AssetManager to grab the files based on those IDs, but you may have to rework your .xml files if you go this route. – Sandalfoot Nov 19 '15 at 21:31

I came to this site looking for a similar question and there are indeed a few good resources pointed both in the answers to your question and in other questions.

You should probably take a look at 2D animation: Animated 3D models or sprites with animation frames? for some debate on different types of animation. It helped me optimize my game. Also, you don't tell us which API you are using or which Engine you use. That alone can make quite a difference: Android frame by frame PNG animation

Besides that, keep in mind that if you will go the compression route, there can be important differences between how you compress. Specifically, there are quite a few differences between types of compression and there is some specialized debate on what is the most appropriate route for mobile devices. Specially if you take into account that for mobile, RAM usage and CPU waste for loading are also paramount. See: http://www.gamasutra.com/blogs/AlexandruVoica/20130419/190833/Why_efficiency_is_key_in_texture_compression_standards_for_mobile_graphics.php?print=1

• Thank you Bennton, I am actually new at game development. I developed lots of apps that are tools/productivity based. But none with games. So I am doing my first game and I am not using an engine. I am using just AnimationDrawables and things are working great. It is just the the size of the apk is getting out of hand – Snake Nov 24 '15 at 4:01
• Bennton, the last link suggested by you is particularly interesting. Many thanks for sharing that! Make sure you take a look at the last one from my answer, which also touches the issue of different compression for different file types. Actually, there seems to be compression types that work better with already compressed image types like PNG, or better with uncompressed image types. Experimenting for each case is always the best way to check what works best for each situation. – MAnd Nov 24 '15 at 23:11