Please share...

  • Video courses

    All game programming videos just $19 - For a very limited time these three videos and thousands more are up to 90% off!

    Just enter coupon code NEWU19 in cart/checkout

Unity Pro Development A to Z – Build 10 Android/iOS Games

The Complete Android & Java Developer Course – Build 21 Apps

The Complete Java Developer Course. Learn Step by Step

This very simple tutorial will quickly bring your games to life by drawing the frames of animation from a row of frames drawn consecutively in the same file. We will see how to draw each of five frames one after the other and after we have drawn the last frame, loop back to the first. I have just updated this tutorial and added an extra code listing to the end which gives an example of how you might encapsulate the animation functionality in a class.

  • Learning java by building Android games

    Learning Java by Building Android Games

    Want to learn Java for Android? Even if you are completely new to either Java, Android, or game programming but are aiming to publish Android games, then this book is for you. This book also acts as a refresher for those who already have experience in Java on other platforms or other object-oriented languages.
    • Setup your own Android game programming environment using Android Studio
    • Control logic, branch your code, and add real decision-making depth to your games
    • Design and use 2d sprite animations, smooth pixel graphics, sound FX, simple collision detection and artificial intelligence (AI)
    • Build around a dozen sample test apps and 4 complete working games!
    Amazon USA
    Amazon UK
    Amazon CA
    Our Store (US only)
    small_book

    Android Game Programming by Example

    Learn to build exciting Android game projects. Build a simple flappy-bird like game to a multi-environment, tough, retro platformer then an OpenGL ES 2 Asteroids clone, running at hundreds of frames per second .
    • Animate your characters with sprite sheets, add multiple scrolling parallax backgrounds, and implement genuinely tough, playable levels in your games
    • Every single line of code is printed in the book! No need to refer to the code files while trying to follow along. All the code files are also supplied separately so you can refer to them in their completed form and copy/paste them into your project if you like.
    • Implement a multitude of other game features such as pickups, firing weapons, HUD’s, generating and playing sound FX, scenery, level transition, high scores, and more
    Amazon USA
    Amazon UK
    Amazon CA
    Our Store (US Only)

About this project

Skill level 1
Time to complete 1 hour

New Concepts:

  1. Internal animations from a sprite sheet
  2. Using official documentation
  3. Overloaded methods

Recommended preparation tutorials

Admittedly Bob isn’t the highest quality graphic and his sprite sheet represents an extremely basic walking motion but once you have this technique in your game programming tool-kit you can swap Bob out for some really high quality sprite sheets and create some graphical masterpieces. There are many free examples to be found with a quick Web search.

Setting up the sprite sheet animation project

To get started create a new project in Android Studio, call it Sprite Sheet Animation and name the Activity SpriteSheetAnimation. Now download the sprite sheet below and add it to the drawable folder of your Android Studio project. Be sure to keep the file name the same. bob.png. Please don’t be confused by the fact that Bob is facing the opposite way in the sprite sheet to that of the explanatory diagrams later in the project. I did the explanatory diagrams first then realized that Bob would be moonwalking backward if I didn’t amend the Building a simple game engine code. And I wanted to keep the code consistent between the two projects so that just the new sprite sheet animation code stands out.

bob

 

Below you can see a representation of bob.png. We can see the height and width of each frame as well as the progression through a simple walking animation. Note that the actual bob.png file background is transparent not white. It just looks white above because of the white background of this page. With this simple sprite sheet animation solution, the width and height of each frame perhaps surprisingly, not relevant. What is key however is the fact that all the widths are the same and that the ratio of the width to the height is important for the sake of maintaining the visual consistency of the displayed image. So take a quick look before moving on.
5_frame_sprite_sheet_explained

Notice in the next, quite large code block that it is nearly identical to the code from the Building a simple game engine project. Review the code below and refer to the comments for a reminder but if anything is unclear refer to that previous project to understand what is going on. Make note of where we will be adding new code to animate Bob to make him look like he is walking. I have added some comments to mark these places.

We will add a bunch of new member variables just after the existing member variables shown below. We will add a few lines of code in the constructor SpriteSheetAnimation() just after we create the bitmap from the bob.png file. We will add a new method called getCurrentFrame that will work the magic of our sprite sheet animation and finally we will change the way that we draw the bitmap to the screen in the draw method. Notice in the code below the original call to drawBitmap is commented out ready for our sprite sheet friendly code.

The starting code from the Simple game engine project

So, delete the entire contents of your SpriteSheetAnimation.java code file with the exception of the package declaration, review and add the code below in its place.

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class SpriteSheetAnimation extends Activity {

    // Our object that will hold the view and
    // the sprite sheet animation logic
    GameView gameView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Initialize gameView and set it as the view
        gameView = new GameView(this);
        setContentView(gameView);

    }

    // Here is our implementation of GameView
    // It is an inner class.
    // Note how the final closing curly brace }
    // is inside SpriteSheetAnimation

    // Notice we implement runnable so we have
    // A thread and can override the run method.
    class GameView extends SurfaceView implements Runnable {

        // This is our thread
        Thread gameThread = null;

        // This is new. We need a SurfaceHolder
        // When we use Paint and Canvas in a thread
        // We will see it in action in the draw method soon.
        SurfaceHolder ourHolder;

        // A boolean which we will set and unset
        // when the game is running- or not.
        volatile boolean playing;

        // A Canvas and a Paint object
        Canvas canvas;
        Paint paint;

        // This variable tracks the game frame rate
        long fps;

        // This is used to help calculate the fps
        private long timeThisFrame;

        // Declare an object of type Bitmap
        Bitmap bitmapBob;

        // Bob starts off not moving
        boolean isMoving = false;

        // He can walk at 150 pixels per second
        float walkSpeedPerSecond = 250;

        // He starts 10 pixels from the left
        float bobXPosition = 10;

        // New variables for the sprite sheet animation

        // When the we initialize (call new()) on gameView
        // This special constructor method runs
        public GameView(Context context) {
            // The next line of code asks the
            // SurfaceView class to set up our object.
            // How kind.
            super(context);

            // Initialize ourHolder and paint objects
            ourHolder = getHolder();
            paint = new Paint();

            // Load Bob from his .png file
            bitmapBob = BitmapFactory.decodeResource(this.getResources(), R.drawable.bob);

        }

        @Override
        public void run() {
            while (playing) {

                // Capture the current time in milliseconds in startFrameTime
                long startFrameTime = System.currentTimeMillis();

                // Update the frame
                update();

                // Draw the frame
                draw();

                // Calculate the fps this frame
                // We can then use the result to
                // time animations and more.
                timeThisFrame = System.currentTimeMillis() - startFrameTime;
                if (timeThisFrame >= 1) {
                    fps = 1000 / timeThisFrame;
                }

            }

        }

        // Everything that needs to be updated goes in here
        // In later projects we will have dozens (arrays) of objects.
        // We will also do other things like collision detection.
        public void update() {

            // If bob is moving (the player is touching the screen)
            // then move him to the right based on his target speed and the current fps.
            if(isMoving){
                bobXPosition = bobXPosition + (walkSpeedPerSecond / fps);
            }

        }

        // Draw the newly updated scene
        public void draw() {

            // Make sure our drawing surface is valid or we crash
            if (ourHolder.getSurface().isValid()) {
                // Lock the canvas ready to draw
                canvas = ourHolder.lockCanvas();

                // Draw the background color
                canvas.drawColor(Color.argb(255, 26, 128, 182));

                // Choose the brush color for drawing
                paint.setColor(Color.argb(255,  249, 129, 0));

                // Make the text a bit bigger
                paint.setTextSize(45);

                // Display the current fps on the screen
                canvas.drawText("FPS:" + fps, 20, 40, paint);

                // Draw bob at bobXPosition, 200 pixels
                //canvas.drawBitmap(bitmapBob, bobXPosition, 200, paint);

                // New drawing code goes here

                // Draw everything to the screen
                ourHolder.unlockCanvasAndPost(canvas);
            }

        }

        // If SimpleGameEngine Activity is paused/stopped
        // shutdown our thread.
        public void pause() {
            playing = false;
            try {
                gameThread.join();
            } catch (InterruptedException e) {
                Log.e("Error:", "joining thread");
            }

        }

        // If SimpleGameEngine Activity is started theb
        // start our thread.
        public void resume() {
            playing = true;
            gameThread = new Thread(this);
            gameThread.start();
        }

        // The SurfaceView class implements onTouchListener
        // So we can override this method and detect screen touches.
        @Override
        public boolean onTouchEvent(MotionEvent motionEvent) {

            switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {

                // Player has touched the screen
                case MotionEvent.ACTION_DOWN:

                    // Set isMoving so Bob is moved in the update method
                    isMoving = true;

                    break;

                // Player has removed finger from screen
                case MotionEvent.ACTION_UP:

                    // Set isMoving so Bob does not move
                    isMoving = false;

                    break;
            }
            return true;
        }

    }
    // This is the end of our GameView inner class

    // This method executes when the player starts the game
    @Override
    protected void onResume() {
        super.onResume();

        // Tell the gameView resume method to execute
        gameView.resume();
    }

    // This method executes when the player quits the game
    @Override
    protected void onPause() {
        super.onPause();

        // Tell the gameView pause method to execute
        gameView.pause();
    }

}

Now, in the code that follows we will add all the required extra member variables.

Adding the sprite sheet control variables

Firstly we have two int variables frameWidth and frameHeight for holding the width and height of the frame. You might notice that we initialize these two variables to two values which are different to the actual sizes of the frames in the bob.png file as shown in the previous image. As we will see this doesn’t matter and you can make Bob’s frames almost any size you like.

Next, we declare another int called frameCount and initialize it to 5 which is the number of frames in the sprite sheet. Then we declare and initialize currentFrame to 0. This variable will perhaps unsurprisingly keep track of which frame is being drawn and as we want to start with frame zero we initialize it accordingly.

The variable lastFrameChangeTime will hold a value in milliseconds representing the time that the last frame was changed. The int variable frameLengthInMilliseconds is how long we would like each frame of animation to last. 100 milliseconds is one-tenth of a second.

After this we declare and initialize an object of type Rect which will hold the coordinates (the four corners) of the current frame within our sprite sheet, so we name it frameToDraw and initialize it with 0 (left), 0(top), frameWidth(right) and frameHeight(bottom) which after we have loaded and scaled bob.png will be the exact first frame of animation.

Finally, in this block of code, we declare and initialize a RectF which is exactly the same as a Rect except it can hold floating point numbers as well. This is ideal because it will hold Bob’s x location which is indeed a float. We name the RectF whereToDraw and initialize it with bobXPosition(left), 0 (top), bobXPosition + frameWidth(right) and frameHeight(bottom). Note the difference between the whereToDraw and frameToDraw objects. The whereToDraw object will be the screen coordinates where we will draw the frame defined by frameToDraw.

Add the code below that we have just discussed at the end of all the previous member variables but before the constructor method just after the // New variables for the sprite sheet animation comment.

        // New variables for the sprite sheet animation

        // These next two values can be anything you like
        // As long as the ratio doesn't distort the sprite too much
        private int frameWidth = 100;
        private int frameHeight = 50;

        // How many frames are there on the sprite sheet?
        private int frameCount = 5;

        // Start at the first frame - where else?
        private int currentFrame = 0;

        // What time was it when we last changed frames
        private long lastFrameChangeTime = 0;

        // How long should each frame last
        private int frameLengthInMilliseconds = 100;

        // A rectangle to define an area of the
        // sprite sheet that represents 1 frame
        private Rect frameToDraw = new Rect(
                0,
                0,
                frameWidth,
                frameHeight);

        // A rect that defines an area of the screen
        // on which to draw
        RectF whereToDraw = new RectF(
                bobXPosition,                0,
                bobXPosition + frameWidth,
                frameHeight);

Now we can add some code in the constructor.

Scaling the sprite sheet to match the frame size

When Android loads a bitmap from a file it scales it differently depending upon the device the program is running on. So it is very unlikely that the bitmapBob = BitmapFactory.decodeResource... line of code which loads bob.png will correspond with our various frameWidth and frameHeight variables. It is possible to put the bob.png file within a specially named folder within the drawable folder which will then instruct Android not to mess with the scale. However, as our game coding progresses we want to respond to things like screen resolution so we will begin to see part of how we will do so here. In the next block of code which we must add right after the previously mentioned  bitmapBob = BitmapFactory.decodeResource... line of code, we take our new Bitmap object, bitmapBob and scale it using Bitmap.createScaledBitmap and scale it to the size of  frameWidth * frameCount, frameHeight. Now we have a sprite sheet which is exactly the correct size for all the variables we declared previously.

Add the code below, just below the  bitmapBob = BitmapFactory.decodeResource... line of code.

            // Scale the bitmap to the correct size
            // We need to do this because Android automatically
            // scales bitmaps based on screen density
            bitmapBob = Bitmap.createScaledBitmap(bitmapBob,
                   frameWidth * frameCount,
                    frameHeight,
                    false);

Now we need a new method that will keep track of our frames and loop through them at the rate contained in frameLengthInMilliSeconds (100 milliseconds per frame).

Getting the current frame

The solution is the getCurrentFrame method that we will now discuss. After the method signature, we initialize time to whatever the time is. Then we check whether the player is currently moving Bob because if he isn’t we know that no matter how much time has elapsed we don’t want to change the frame. If isMoving is true we check if time is greater than the time we last changed the frame of animation added to the length of time we want each frame to be visible for. If it is then we set lastFrameChangeTime to the current time ( time) ready for the next time we call this method. Then we simply increment the current frame with currentFrame ++.

Next, we check to see if currentFrame has exceeded the frameCount and if it has it is time to go back to the first frame and currentFrame is set to zero. Now outside of all the if statements we want to set frameToDraw to hold the four corners of whatever the current frame of animation is.

This is achieved by setting frameToDraw.left to currentFrame multiplied by frameWidth and frameToDraw.right to whatever frameToDraw.left now is + frameWidth. The Rect frameToDraw now holds the coordinates of the current frame. Enter the new method getCurrentFrame. It can go anywhere within the SpriteSheetAnimation class as long as it is not inside another method.

       public void getCurrentFrame(){

            long time  = System.currentTimeMillis();
            if(isMoving) {// Only animate if bob is moving
                if ( time > lastFrameChangeTime + frameLengthInMilliseconds) {
                    lastFrameChangeTime = time;
                    currentFrame ++;
                    if (currentFrame >= frameCount) {

                        currentFrame = 0;
                    }
                }
            }
            //update the left and right values of the source of
            //the next frame on the spritesheet
            frameToDraw.left = currentFrame * frameWidth;
            frameToDraw.right = frameToDraw.left + frameWidth;

        }

Finally, we will get to draw Bob.

Drawing the frames of animation

In the next block of code, you can see the old call to canvas.drawBitmap has been commented out. Immediately after this, we call whereToDraw.set and initialize it with the coordinates on the screen where we want to draw a frame of Bob. We use bobXPosition (for left), (for top), bobXPosition + frameWidth (for right) and frameHeight (for the bottom).

Then we call getCurrentFrame which loads the coordinates of the current frame of animation into frameToDraw. The last line of code calls an overloaded version of drawBitmap to draw the appropriate frame from the sprite sheet to the appropriate coordinates on the screen. Take a look at the drawing below to understand this last line of code.

how_drawBitmap_uses_sprite_sheet

 

Overloaded methods are methods that can take multiple different parameters but still have the same name. Now would be a good time to start exploring the official Android documents for the first time if you haven’t ever done so before. Here you can see all the different versions of drawBitmap and the arguments you can use to get stuff drawn to the screen with it. Getting used to the dry, technical but extremely useful official documentation is invaluable. Here is a link to the ins and outs of the Canvas class which includes explanations for several overloaded versions of drawBitmap.

Add these final lines of code in the draw method at the position indicated by the commented out code.

                // Draw bob at bobXPosition, 200 pixels
                //canvas.drawBitmap(bitmapBob, bobXPosition, 200, paint);

                // New drawing code goes here
                whereToDraw.set((int)bobXPosition,
                        0,
                        (int)bobXPosition + frameWidth,
                        frameHeight);

                getCurrentFrame();

                canvas.drawBitmap(bitmapBob,
                        frameToDraw,
                        whereToDraw, paint);

Final thoughts

You can now run the project and watch Bob stroll confidently and fairly smoothly across the screen. We will use this technique for sprite sheet animation in an upcoming game project where we will see how to wrap this functionality up in a class of its own so it can be used for multiple different animated game objects while only writing the code once. Sprite sheet animation is also discussed at length in my book Android Game Programming by Example.

complete coded listing from SpriteSheetAnimation.java

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class SpriteSheetAnimation extends Activity {

    // Our object that will hold the view and
    // the sprite sheet animation logic
    GameView gameView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Initialize gameView and set it as the view
        gameView = new GameView(this);
        setContentView(gameView);

    }

    // Here is our implementation of GameView
    // It is an inner class.
    // Note how the final closing curly brace }
    // is inside SpriteSheetAnimation

    // Notice we implement runnable so we have
    // A thread and can override the run method.
    class GameView extends SurfaceView implements Runnable {

        // This is our thread
        Thread gameThread = null;

        // This is new. We need a SurfaceHolder
        // When we use Paint and Canvas in a thread
        // We will see it in action in the draw method soon.
        SurfaceHolder ourHolder;

        // A boolean which we will set and unset
        // when the game is running- or not.
        volatile boolean playing;

        // A Canvas and a Paint object
        Canvas canvas;
        Paint paint;

        // This variable tracks the game frame rate
        long fps;

        // This is used to help calculate the fps
        private long timeThisFrame;

        // Declare an object of type Bitmap
        Bitmap bitmapBob;

        // Bob starts off not moving
        boolean isMoving = false;

        // He can walk at 150 pixels per second
        float walkSpeedPerSecond = 250;

        // He starts 10 pixels from the left
        float bobXPosition = 10;

        // New for the sprite sheet animation

        // These next two values can be anything you like
        // As long as the ratio doesn't distort the sprite too much
        private int frameWidth = 100;
        private int frameHeight = 50;

        // How many frames are there on the sprite sheet?
        private int frameCount = 5;

        // Start at the first frame - where else?
        private int currentFrame = 0;

        // What time was it when we last changed frames
        private long lastFrameChangeTime = 0;

        // How long should each frame last
        private int frameLengthInMilliseconds = 100;

        // A rectangle to define an area of the
        // sprite sheet that represents 1 frame
        private Rect frameToDraw = new Rect(
                0,
                0,
                frameWidth,
                frameHeight);

        // A rect that defines an area of the screen
        // on which to draw
        RectF whereToDraw = new RectF(
                bobXPosition,                0,
                bobXPosition + frameWidth,
                frameHeight);

        // When the we initialize (call new()) on gameView
        // This special constructor method runs
        public GameView(Context context) {
            // The next line of code asks the
            // SurfaceView class to set up our object.
            // How kind.
            super(context);

            // Initialize ourHolder and paint objects
            ourHolder = getHolder();
            paint = new Paint();

            // Load Bob from his .png file
            bitmapBob = BitmapFactory.decodeResource(this.getResources(), R.drawable.bob);

            // Scale the bitmap to the correct size
            // We need to do this because Android automatically
            // scales bitmaps based on screen density
            bitmapBob = Bitmap.createScaledBitmap(bitmapBob,
                   frameWidth * frameCount,
                    frameHeight,
                    false);

            // Set our boolean to true - game on!
            //playing = true;

        }

        @Override
        public void run() {
            while (playing) {

                // Capture the current time in milliseconds in startFrameTime
                long startFrameTime = System.currentTimeMillis();

                // Update the frame
                update();

                // Draw the frame
                draw();

                // Calculate the fps this frame
                // We can then use the result to
                // time animations and more.
                timeThisFrame = System.currentTimeMillis() - startFrameTime;
                if (timeThisFrame >= 1) {
                    fps = 1000 / timeThisFrame;
                }

            }

        }

        // Everything that needs to be updated goes in here
        // In later projects we will have dozens (arrays) of objects.
        // We will also do other things like collision detection.
        public void update() {

            // If bob is moving (the player is touching the screen)
            // then move him to the right based on his target speed and the current fps.
            if(isMoving){
                bobXPosition = bobXPosition + (walkSpeedPerSecond / fps);
            }

        }

        public void getCurrentFrame(){

            long time  = System.currentTimeMillis();
            if(isMoving) {// Only animate if bob is moving
                if ( time > lastFrameChangeTime + frameLengthInMilliseconds) {
                    lastFrameChangeTime = time;
                    currentFrame++;
                    if (currentFrame >= frameCount) {

                        currentFrame = 0;
                    }
                }
            }
            //update the left and right values of the source of
            //the next frame on the spritesheet
            frameToDraw.left = currentFrame * frameWidth;
            frameToDraw.right = frameToDraw.left + frameWidth;

        }

        // Draw the newly updated scene
        public void draw() {

            // Make sure our drawing surface is valid or we crash
            if (ourHolder.getSurface().isValid()) {
                // Lock the canvas ready to draw
                canvas = ourHolder.lockCanvas();

                // Draw the background color
                canvas.drawColor(Color.argb(255,  26, 128, 182));

                // Choose the brush color for drawing
                paint.setColor(Color.argb(255,  249, 129, 0));

                // Make the text a bit bigger
                paint.setTextSize(45);

                // Display the current fps on the screen
                canvas.drawText("FPS:" + fps, 20, 40, paint);

                // Draw bob at bobXPosition, 200 pixels
                //canvas.drawBitmap(bitmapBob, bobXPosition, 200, paint);

                whereToDraw.set((int)bobXPosition,
                        0,
                        (int)bobXPosition + frameWidth,
                        frameHeight);

                getCurrentFrame();

                canvas.drawBitmap(bitmapBob,
                        frameToDraw,
                        whereToDraw, paint);

                // Draw everything to the screen
                ourHolder.unlockCanvasAndPost(canvas);
            }

        }

        // If SimpleGameEngine Activity is paused/stopped
        // shutdown our thread.
        public void pause() {
            playing = false;
            try {
                gameThread.join();
            } catch (InterruptedException e) {
                Log.e("Error:", "joining thread");
            }

        }

        // If SimpleGameEngine Activity is started theb
        // start our thread.
        public void resume() {
            playing = true;
            gameThread = new Thread(this);
            gameThread.start();
        }

        // The SurfaceView class implements onTouchListener
        // So we can override this method and detect screen touches.
        @Override
        public boolean onTouchEvent(MotionEvent motionEvent) {

            switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {

                // Player has touched the screen
                case MotionEvent.ACTION_DOWN:

                    // Set isMoving so Bob is moved in the update method
                    isMoving = true;

                    break;

                // Player has removed finger from screen
                case MotionEvent.ACTION_UP:

                    // Set isMoving so Bob does not move
                    isMoving = false;

                    break;
            }
            return true;
        }

    }
    // This is the end of our GameView inner class

    // This method executes when the player starts the game
    @Override
    protected void onResume() {
        super.onResume();

        // Tell the gameView resume method to execute
        gameView.resume();
    }

    // This method executes when the player quits the game
    @Override
    protected void onPause() {
        super.onPause();

        // Tell the gameView pause method to execute
        gameView.pause();
    }

}

Please visit the Android category of our game coding bookstore for beginners

 

Encapsulating the animation in an Animation class

A few people have asked how you might wrap the animation up into a class. Here is some code that is one way of doing it, there are others. I haven’t got time at the moment to fully explain or add code changes for the code that uses it but you will see that most of the variables and method names remain the same or similar to the tutorial and code above. Obviously, you will need to make changes to the code that uses the class yourself. I hope this helps a bit.


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;

public class Animation {
    Bitmap bitmapSheet;
    String bitmapName;
    private Rect sourceRect;
    private int frameCount;
    private int currentFrame;
    private long frameTicker;
    private int framePeriod;
    private int frameWidth;
    private int frameHeight;
    int pixelsPerMetre;

    Animation(Context context, String bitmapName, float frameHeight, float frameWidth,
              int animFps, int frameCount, int pixelsPerMetre){

        this.currentFrame = 0;
        this.frameCount = frameCount;

        this.frameWidth = (int)frameWidth * pixelsPerMetre;
        this.frameHeight = (int)frameHeight * pixelsPerMetre;
        sourceRect = new Rect(0, 0, this.frameWidth, this.frameHeight);
        framePeriod = 1000 / animFps;
        frameTicker = 0l;
        this.bitmapName = "" + bitmapName;
        this.pixelsPerMetre = pixelsPerMetre;
    }
    public Rect getCurrentFrame(long time, float xVelocity, boolean moves){

        if(xVelocity!=0 || moves == false) {// Only animate if the object is moving or it is an object which doesn't move
            if (time > frameTicker + framePeriod) {
                frameTicker = time;
                currentFrame++;
                if (currentFrame >= frameCount) {
                    //if (currentFrame >= frameCount) {
                    currentFrame = 0;
                }
            }
        }
        //update the left and right values of the source of
        //the next frame on the spritesheet
        this.sourceRect.left = currentFrame * frameWidth;
        this.sourceRect.right = this.sourceRect.left + frameWidth;

        return sourceRect;
    } 

}