Getting Started: Working with Images

Next, let’s take a look at working with images. AndEngine has a few tools that are important for loading images into memory, setting them up for use, and making sure they work well and efficiently.

Why it can’t be simple

When I got started with game programming, I tried to just give each sprite an image whenever it spawned. I didn’t want to have to deal with texture regions, so I simply ignored them. However, when it actually game time to run my game- it ran like garbage. Everything worked much more slowly than it should have, because not only did I not tell the game not store the pictures in memory- I also had them just a few pixels too big for Android to work with. I didn’t put the effort in to understand how to work with image, and my performance suffered as a result. Hopefully, we can avoid letting that happen to you!

What are Textures?

In modern game environments, the system’s memory allocates in size to the power of 2. What this means for you as the programmer is that it is best to make your pictures as close to the power of 2 as is possible. Therefore, your image can be 2×2 sprites, 4×4, 8×8, 16×16, 32×32, 64×64, 128×128, 256×256, 512×512, 1024×1024, ect. Also, the dimensions don’t have to be the same- you can have an image that is 512×256, 4×1024 (though I’m not sure why you would want that one)- without wasting memory.

So, what if it doesn’t end up a power of two? The system allocates that memory as empty memory, and it is wasted. This is one of the reasons why my game took up so much memory- because my 260×260 images were taking up almost twice the amount of space that they actually occupied in memory!

This is where Textures and TextureRegions come in. AndEngine allows you to dynamically fill in those blank spaces with different images in order to make a single Texture Atlas- one image, with each region defined as a different section of that image. By using a TextureRegion, you can save memory in your app, while keeping the image defined in memory- thus resulting in an image that stays in memory and can be used for dozens of sprites with very little slowdown at all!

So- what are the pieces of code necessary to put all this together?

BitmapTextureAtlas

The BitmapTextureAtlas is the picture that is loaded into the memory. It will be your final product- and as such, it needs to be defined first. First, it’s a good idea to define it in the base of the class with the other fields and constants, like so:

private BitmapTextureAtlas mBitmapTextureAtlas;

Next, we begin to work with it in the onLoadResources() section of the code like this:

When the BitmapTextureAtlas is defined, it includes three variables. The first two are the height and width of the texture atlas. In this example, it is given a height of 1024 and a width of 512. The third is a quality of how the picture will be rendered. For most uses, TextureOptions.BILINEAR_PREMULTIPLYALPHA will do just fine here.

There is one last thing I would like to mention in this section: how to set the base path. It’s a good idea to place your image in a separate path to keep your project organized, and that includes putting all your images in a separate folder. It can simplify your code and make any future changes easier if you set the base path of your texture region factory (where your images are stored) like this:

BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

There you have it! This is how you create your Bitmap Texture Atlas. Next, we need to load it with images!

BitmapTextureRegion

To place an image onto your atlas, you need to create a TextureRegion. Just like TextureAtlases, TextureRegions should be defined in the base of the class as they will be used in multiple parts of the app, like so:

Okay- what’s going on here? What we’re doing is telling the BitmapTextureAtlasTextureRegionFactory (the device built into AndEngine that puts the textures together) to add an image to the texture region. To do so, it takes a number of inputs:

(1) the Texture Region you want it to be a part of

(2) the base context (this usually works fine here)

(3) the texture to be loaded into the atlas

(4) the X offset of the image on the region

(5) The Y offset of the image on the region

Most of these are self-explanatory, but let’s take a quick look at #4 and #5- they’re used to let the image factory know where in the texture region to place the particular image. If you leave this at 0, the second image will overwrite the first one! If you run into a situation in which an image is partially obscured by another image when loaded, the offset is almost definitely the problem- just make sure to allocate things so that they don’t run into each other!

Loading into the engine

There is one last step before the setup is complete- we need to load the bitmap texture atlas into the engine. To do this,

This code loads the texture atlas into the engine (with an extra atlas, myBackgroundTextureAtlas, stuck in there to show you how to add multiple texture atlases at once).

Which Image Files to Use

So, what do we put into our Texture Regions? It may be tempting to use the smallest format available- such as a compressed jpg, or a gif- but it’s not always the best idea. My suggestion- in most cases, use Png. Png files have a number of benefits to them- they are lossless, which means you’re going to be getting the image at full quality, and they have transparency, meaning if you have any places where the user should be able to see through the sprite, they will be able to do so. (These make Png such a popular choice that some even say it stands for Please not Gif!)

For working with your images, the best picture editing program is Photoshop, but if you’re an amateur developer, you’re probably not ready to shell out the hundreds of dollars required to purchase a professional copy. If you are looking for a good free picture editing program, the two main alternatives are Paint.net and Gimp. There is also a handy free flash-based picture editor that works quite well called pixlr– though you should be aware that though it has great capabilities, you have to intentionally save it with layers, or they will be lost when closed.

Hopefully these tools will have your pictures up and running smoothly- you’ll need it for our next guide, Getting Started: Backgrounds!

Glad you like them, AB10! Unfortunately, school has gotten quite a bit more difficult lately, so I’ve been a bit slower recently. I’ve got a few that I’m hoping to work on when things aren’t quite so busy, though!

Hi guys, thank you for useful post!
I have a difficulty when I want to detect onAreaTouch with images which do not have size of 2 power n. For example, I often work on iPhone 320×480 size. So I cover them with a transparent
512×512 to match 2 power n size.
I wonder what is the good way to detect real image size in this case?
Should we detect pLocalTouchEvent and compare with the real size?
Thank you and appreciate for any helps!!!

I just want to say I really appreciate these tutorials! I really like what AndEngine has to offer but the lack of documentation has made it difficult for me to develop on it. Please keep these tutorials coming when you have time.