Day 19: Our First Animation

What we have done so far in this tutorial series was to create an essential framework for displaying 2-dimensional texture graphics. Today we are going to see this framework in action.

Introduction

From day 4 we remember that the fundamental parts of our framework are stage, scenes, and sprites. We completed designing the Stage class last day. We saw that the stage can only have one scene at any given time. If our game has four main screens, then one of four scenes will be set as current according to our game’s logic:

Stage and Scenes

What we know for sure is that we need at least one scene. In day 16 we designed the Scene class. Every scene we have in our app should be a subclass of this class. Each scene consists of a series of sprites (contained in sprite layers). Today we only work with a single sprite.

Creating the Scene

Navigate to the app module, and add a class named MyScene next to MainActivity. This class should extend Scene. Start with the following code:

public class MyScene extends Scene {
    public MyScene(Stage parentStage) {
        super(parentStage);
    }
}

This simply creates a scene associated with the given stage. This will be our only scene in today’s app. In order to use it, open the MainActivity, and find this line:

stage = (Stage)findViewById(R.id.my_stage);

and add the following code below this line:

stage.setScene(new MyScene(stage));

Believe it or not, your stage will be rendering the content of MyScene, which is… nothing for now.

Declaring the Texture

Next step is to create an image sprite. As we are seeking an animated sprite, an image atlas of the corresponding frames would be desirable. You can make your own, or use the following character animation from my game Hungry Slimes (click on the image to download):

Slime Animation Atlas

If you are making your own, make sure your frames’ bounding boxes are exactly 128×128 pixels and are in a horizontal line. Also make sure you have at least 7 frames, and the width of your
atlas is a power of two. The framework does not currently handle non-power-of-two images automatically.

Create a folder called drawable under the res folder of your app module, if it doesn’t already exist, and save the above image (or your own image) in that folder. We should also tell the texture manager about the texture we are going to use. So, add the following code to your MainActivity, just before you add the scene to the stage:

TextureManager.add(new int[]{R.drawable.slime});

Again, in case of customized atlas, replace slime with your image name.

Setting Up the Scene

Open the MyScene class. The Scene class has a method called onLoaded, which is called right after everything else is loaded. Scenes should override and build their contents in this method. That is what we do for MyScene:

@Override
public void onLoaded() {
    setBackColor(new RGB("ffffff"));

    /* Let the stage know that this scene is fully loaded */
    super.onLoaded();
}

What it does as of now is just to set the background color of the scene to white. We now need to add a sprite to this scene. Continue the method with the following code:

ImageSprite.Cutout cutout = new ImageSprite.Cutout(128, 128, 7);
ImageSprite sprite = new ImageSprite(R.drawable.slime, cutout);
sprite.setPosition(300, 300);
add(sprite, 0);

If you remember from day 12, cutouts tell the image sprite how to split the atlas into its frames. The first line in the above code means that the image contains 7 frames of size 128×128 pixels, starting at the bottom-left corner (the last part is implied as not explicitly specified in the call). We pass this cutout rule, as well as the slime image to the image sprite’s constructor. Then we set the position of the sprite. The last line simply adds the sprite to the first layer of the scene.

Animation

Even though our sprite has 7 frames according to its cutout, it will show only the first frame if we run the project now. That’s where animation handlers come in. Using an image animation, we can make the image sprite cycle through its frames.

AnimationHandler animation = new ImageAnimation(
        new int[] {0, 1, 2, 3, 4, 5, 6},
        ImageAnimation.TREND_PINGPONG
);
sprite.setAnimation(animation);

What the first line does (first four lines!) is to create an image animation that goes through all frames 0 to 6. It also sets the trend to ping-pong, meaning that it will go back-and-fourth (0 to 6, back to 0, back to 6, and so on). As our slimy character closes its mouth in one sweep of the frames, it keeps opening and closing it in a ping-pong animation.

You can now run the project and see the results (which look like below animation)!

Slime Animation

Next steps

Today was a milestone in the development of our game framework. If you have been only following this tutorial series to learn the basics of 2D animation with OpenGL ES, you now have everything you need to continue your own journey. What we discuss after today might not be directly related to OpenGL, but subjects around the development of a game framework. Artenus, as it stands in today’s post, is a bedrock for you to play around and experiment with OpenGL ES and see the results immediately. We will continue expanding this bedrock in the next few posts. In Part 4 of the tutorial, we will re-factor the library, and greatly focus on designing an extensible version of the framework. If you are a computer science enthusiast, you will enjoy Part 4. Later parts of the tutorial will cover other aspects of the framework (sound, controls, IAP, etc).

You can download the individual files for today’s tutorial here:

You may also download source code for all classes.