Greetings!

The main purpose of this website is to support Android indie game developers with tutorials, reviews and promotion of their games. The main difficulty for the developers is not to make the game, but to get exposure. To get it out there. If you find anything useful here, please spread the word. Like my page on Facebook, follow me on Google+ or Twitter. Thank you!

Google+ Facebook Twitter

× close

Sunday 27 October 2013

AndEngine Tutorial - Dealing with screen sizes and ratios, Resolution Policy explained

Android platform suffers from variety of different screen sizes and ratios. AndEngine tries to deal with this by letting you specify one resolution and then scaling the resulting picture to any device.

You don't need to care whether the screen size of the phone is bigger than your desired resolution  (AndEngine can enlarge your scene) or smaller (AndEngine can shrink your scene). You place your sprites at coordinates in your resolution. However you still have to hint AndEngine how should the resulting picture be scaled (if at all). And that's what Resolution Policy is for.

You might want to have multiple sets of textures for let's say two or three typical resolutions. For example low-res, normal and HD textures. But that is a more advanced topic.

Let's say you want to work with resolution 800x480px. Your sprite is 80x80px large. Let's add three of them to the scene. So this is how you want your scene to look like. The bottom left square is placed at [50, 50]. AndEngine calculates where to display it in different resolutions.



And here is the part of the Activity where you set up the policy:



private static final int CAMERA_WIDTH = 800;
private static final int CAMERA_HEIGHT = 480;

@Override
public EngineOptions onCreateEngineOptions() {

  final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
  
  return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, 
      new XXXResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);

}

Where XXXResolutionPolicy is your desired setting. Let's see how different policies looks like.

FixedResolutionPolicy 

This policy simply creates a renderable area of specified size. If your screen is 1280x768px like on this Nexus, the 800x480px scene will be centered with big border. If your screen size is exactly 800x480px, your scene will perfectly fit on your display. And if your device has smaller resolution, the whole scene will be cropped. This policy keeps aspect ration of pixels (squares will be squares).


You can of course pass anything to your Fixed Resolution Policy. It doesn't have to be the same as camera dimensions. You can measure the display size of the device and then manually position all elements based on this meassurement. That's what this policy is for.

FillResolutionPolicy

As the name suggests, this policy fills the whole screen with your scene. Your scene will be resized but aspect ratio will not be kept, unless the phone and your scene have the same ratio. Pixels become taller or wider.

You can see that on Nexus 4 the difference is almost not noticeable, because 800x480px ratio is about 1.66, and Nexus 4 screen ratio 1280x768 is 1.66 too. But thanks to the soft buttons in system bar the usable portion has roughly 1.56 screen ratio and that's why the squares are slightly taller.

RelativeResolutionPolicy

If anyone ever finds a good use for this policy, let me know. You have to pass two floats in this one. The percentage of width and height of the screen you want to use. So if you pass (1, 1) it means "give me whole screen" (same as Fill). Maybe good for experiments.

RatioResolutionPolicy

Probably the most common in the examples. It keeps the aspect ratio and scales your scene to fit one dimension. The other dimension will be padded with background color of your theme. it will create two bars. I painted them yellow to make them more visible.



If you set your background theme to be black and your game is a space shooter, I guess you will be fine. But it can still be distracting.

CropResolutionPolicy

This one was originally created by user jgibbs on AndEngine forums. He called it CroppedResolutionPolicy. I have created my own version when I was trying to understand how these policies work. My version has few helper methods that I use in the example below. It is made for GLES2-AnchorCenter version of AndEngine.

Crop policy is similar to Ratio, but instead of padding, it scales the scene while keeping aspect ratio to cover the whole screen and crops the overflow.

This policy is my favourite, but it's not the easiest to use. You must be placing the objects relatively to edges. Center of the screen will still be center, but you can't simply say: place sprite at [0, 0]. It might be in the overflow on some devices.

CropResolutionPolicy example

In this example, I have simply placed 8 rotating squares to the corners and sides of the scene. You can try running the example on different phones or resolutions, and they should stick to the corners and sides every time. Here is the runnable source code. Remember, you need my version of CropResolutionPolicy to run it. It is part of my forked AndEngine GitHub repository.



package is.kul.tutorial.policies;

import java.io.IOException;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.CropResolutionPolicy;
import org.andengine.entity.modifier.LoopEntityModifier;
import org.andengine.entity.modifier.RotationByModifier;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.util.FPSLogger;
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.util.adt.color.Color;


public class MainActivity extends SimpleBaseGameActivity {
  private static final int CAMERA_WIDTH = 800;
  private static final int CAMERA_HEIGHT = 480;
  private static final int SQUARE_SIZE = 64;
  
  CropResolutionPolicy crp;
  
  @Override
  public EngineOptions onCreateEngineOptions() {
    final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
    crp = new CropResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT);
    return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, 
        crp, camera);
  }

  @Override
  public void onCreateResources() throws IOException {
  }

  @Override
  public Scene onCreateScene() {

    this.mEngine.registerUpdateHandler(new FPSLogger());

    final Scene scene = new Scene();
    scene.getBackground().setColor(Color.YELLOW);
    
    final float centerX = CAMERA_WIDTH / 2;
    final float centerY = CAMERA_HEIGHT / 2;
    float left = crp.getLeft();
    float bottom = crp.getBottom();
    float right = crp.getRight();
    float top = crp.getTop();
    
    addRectangle(scene, Color.RED, left, top);
    addRectangle(scene, Color.RED, left, bottom);
    addRectangle(scene, Color.RED, right, top);
    addRectangle(scene, Color.RED, right, bottom);
    
    addRectangle(scene, Color.GREEN, left, centerY);
    addRectangle(scene, Color.GREEN, right, centerY);
    addRectangle(scene, Color.GREEN, centerX, top);
    addRectangle(scene, Color.GREEN, centerX, bottom);

    return scene;
  }

  private void addRectangle(final Scene scene, Color color, float left, float top) {
    Rectangle r = new Rectangle(left, top, SQUARE_SIZE, SQUARE_SIZE, getVertexBufferObjectManager());
    r.registerEntityModifier(new LoopEntityModifier(new RotationByModifier(5f, 360f)));
    r.setColor(color);
    scene.attachChild(r);
  }

}

This is how it should look like on any kind of phone in every resolution with any aspect ratio. Of course, the squares will be closer together on X axis in 4:3 and further apart on Y axis and vice versa for 16:9...


Further reading

You can see the list of books about Android Game Development for further reading, not just about AndEngine but game development in general.
Martin Varga is a Czech software developer who likes pygmy owls (hence Kulíš), running, ramen, travelling and living in foreign countries. He is also known as smartus or sm4 on the internet (read as smartass, but there are too many of them). He currently tries to make games in AndEngine like Mr. Dandelion's Adventures and hangs around a lot at the AndEngine forums.